home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 2 / ETO Development Tools 2.iso / Essentials / MPW 411 / InsideMacintoshHelp < prev    next >
Encoding:
Text File  |  1990-10-24  |  6.1 MB  |  135,132 lines  |  [TEXT/MPS ]

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1. æKY CopyrightNotice
  2. æC  Copyright Apple Computer, Inc. 1985-1990, All rights reserved.
  3. 411 - Inside Macintosh Help - MPW 3.2 Beta Release.
  4. Monday, October 22, 1990 9:00:00 AM
  5.  
  6. Information source: SpInsideMacintosh 1.0 HyperCard stack.
  7.                     Pegasus 1.2.5 Hypercard Stack  IM Vol VI
  8. æKY Help
  9. InsideMacintoshHelp
  10. æC 
  11. AboutInsideMacintoshHelp   Preface                   UserInterfaceGuidelines        
  12. IntroductiontoSystem7.0    RoadMap                   WorldwideSoftwareOverview
  13.                                                      
  14.                      
  15. AliasManager               HelpManager               ScriptManager              
  16. AppleTalkManager           ListManager               SCSIManager
  17. ColorManager               MemoryManager             ShutdownManager   
  18. ControlManager             MenuManager               SlotManager
  19. DatabaseAccessManager      NotificationManager       SoundManager     
  20. DeferredTaskManager        OSEventManager            StartManager 
  21. DeskManager                PackageManager            TimeManager
  22. DeviceManager              PaletteManager            ToolboxEventManager  
  23. DialogManager              PowerManager              VerticalRetraceManager              
  24. EditionManager             PrintingManager           WindowManager
  25. EventManager               ProcessManagement                 
  26. FileManager                QuickDraw                 
  27. FontManager                ResourceManager           
  28. GraphicsDevicesManager     ScrapManager
  29.  
  30.  
  31. AppleDesktopBus            FloatingPointPackage      SoundDriver                     
  32. BinaryDecimalConversion    GraphicsOverView          StandardFile
  33. ColorPickerPackage         InternationalUtilities    SystemErrorHandler      
  34. ColorQuickDraw             MacintoshHardware         SystemResourceFile
  35. CompatibilityGuidelines    MemoryManagement          TextEdit
  36. ControlPanels              OSUtilities               ToolboxUtilities
  37. DiskDriver                 PPCToolbox                UsingAssemblyLanguage
  38. DiskInitialization         SegmentLoader                
  39. FinderInterface            SerialDrivers                                         
  40.  
  41.  
  42. A.ResultCodes              C.SystemTraps             SystemErrors
  43. B.MovesMemory              D.GlobalVariables         Glossary
  44.  
  45.  
  46.  
  47.  
  48. æKY AboutInsideMacintoshHelp
  49. æC
  50. ------------------------------------------------------------------------------
  51.  Version 1.0 Beta:
  52.  
  53.  Volume VI chapters have been added to this version which contain information
  54.  about System 7.0, new managers and changes to previous ones. 
  55.  
  56.  New manager chapters are:               
  57.     AppleTalk Manager                                             
  58.     DatabaseAccess Manager
  59.     Edition Manager
  60.     Event Manager
  61.     GraphicDevices Manager (Replaces the Graphic Devices chapter in Volume V) 
  62.     Help Manager
  63.     Memory Management
  64.     Power Manager
  65.     PPC Toolbox
  66.     Process Management
  67.  
  68. Changed chapters are:
  69.     Alias Manager 
  70.     Color Picker Package
  71.     Color Quikdraw
  72.     Control Panels
  73.     File Manager
  74.     FinderInterface
  75.     Font Manager
  76.     Notification Manager
  77.     Palette Manager
  78.     Resource Manager
  79.     Slot Manager
  80.     Sound Manager
  81.     TextEdit
  82.     Time Manager
  83.     
  84. New/changed documentation chapters are:
  85.     Compatibility Guidelines
  86.     Graphics Overview
  87.     Introduction to System 7.0
  88.     Preface
  89.     UserInterface Guidelines VI
  90.     Worldwide Software Overview
  91.  
  92. ------------------------------------------------------------------------------
  93.  Version 1.0 Alpha:
  94.  
  95.  InsideMacintoshHelp file provides on-line documentation for the 411 project.
  96.  This version contains all the chapters of InsideMacintosh Volumes I - V.  
  97. æKY AliasManager
  98. æC 
  99. _______________________________________________________________________________
  100.  
  101. ALIAS MANAGER
  102. _______________________________________________________________________________
  103.  
  104. About…the…Alias…Chapter
  105. About…the…Alias…Manager
  106. About…Alias…Records
  107. Strategies…for…Resolving…Alias…Records
  108.     Fast…Search
  109.     Slow…Search
  110. Using…the…Alias…Manager
  111.     Creating…Alias…Records
  112.     Resolving…Alias…Records
  113.     ResolveAlias
  114.     SelectAlias
  115.     MatchAlias
  116.     Reading…Alias…Records
  117.     Maintaining…Alias…Records
  118.     Storing…and…Retrieving…Alias…Records
  119. Alias…Manager…Routines
  120.     Creating…and…Updating…Alias…Records
  121.     Resolving…and…Reading…Records
  122. Summary…of…the…Alias…Manager
  123.     Alias…Constants
  124.     Alias…Data…Types
  125.     Alias…Routines
  126.     Alias…Result…Codes
  127.     Assembly-Language…Information…for…Alias
  128. _______________________________________________________________________________
  129.  
  130.  
  131.  
  132. æKY About…the…Alias…Chapter
  133. æC »ABOUT THIS CHAPTER                                     Alias Manager
  134. _______________________________________________________________________________
  135.  
  136. This chapter describes how your application can use the Alias Manager to
  137. establish and resolve alias records, which are data structures that describe a
  138. file, folder, or volume.
  139.  
  140. You create an alias record to take a fingerprint of an object, usually a file,
  141. that you might need to locate again later. If you store the alias record,
  142. instead of a conventional file specification such as name and parent directory
  143. ID, you can later use the Alias Manager’s algorithms for finding files that have
  144. been moved, renamed, copied, or restored from backup.
  145.  
  146. Note:  The Alias Manager is a utility for exploiting alias records.  It does not
  147.  
  148.        directly manipulate desktop aliases, which are created and managed by the
  149.  
  150.        Finder.  (The Finder Interface chapter describes desktop aliases.)
  151.  
  152. The Alias Manager is available only in system software version 7.0. Call the
  153. Gestalt function, described in the Compatibility Guidelines chapter of this
  154. volume, to determine whether the Alias Manager is present.
  155.  
  156. Read this chapter if you want your application to create and resolve alias
  157. records. You might use an alias record, for example, to identify a customized
  158. dictionary from within a text document. When the user runs a spelling checker on
  159. the document, your application can ask the Alias Manager to resolve the record
  160. to find the correct dictionary.
  161.  
  162. To use this chapter, you should be familiar with the File Manager’s conventions
  163. for identifying files, folders, and volumes, as described in the File Manager
  164. chapters in volume IV and this volume.
  165.  
  166. _______________________________________________________________________________
  167.  
  168. æKY About…the…Alias…Manager
  169. æC »ABOUT THE ALIAS MANAGER                                                  Alias Manager
  170. _______________________________________________________________________________
  171.  
  172. The Alias Manager creates and resolves alias records. The next section, “About
  173. Alias Records,” describes how you can use alias records.
  174.  
  175. In general, you should use the Alias Manager whenever you find yourself storing
  176. specific file or directory information such as full pathname or filename and
  177. parent directory ID. The Alias Manager stores this information and more in the
  178. alias record, and it also provides a set of search strategies for resolving the
  179. record later. The search strategies are described in “Resolving Alias Records,”
  180. later in this chapter.
  181.  
  182. You can use the Alias Manager to
  183.   •   create and resolve alias records
  184.   •   get information from and update alias records
  185.  
  186. The Alias Manager can track files and folders across volumes. If the target of
  187. an alias record is on an unmounted AppleShare® volume, the Alias Manager can
  188. automatically initiate the mounting when it resolves the alias. If the target
  189. object is on an unmounted ejectable disk, the Alias Manager can prompt the user
  190. to insert the disk.
  191.  
  192. When the Alias Manager creates an alias record, it fills in the record and
  193. returns a handle to it. Your application must store and retrieve the records on
  194. disk if necessary. Your application must also supply strategies for handling
  195. various alias-resolution problems, described in “Resolving Alias Records.”
  196.  
  197. To help you understand and use the Alias Manager, this chapter provides
  198.   •   an overview of alias records
  199.   •   a description of how the Alias Manager resolves alias records
  200.   •   specific techniques for using the Alias Manager in your application
  201. _______________________________________________________________________________
  202.  
  203. æKY About…Alias…Records
  204. æC »ABOUT ALIAS RECORDS                                                      Alias Manager
  205. _______________________________________________________________________________
  206.  
  207. An alias record is a data structure that describes a file, folder, or volume.
  208. The record contains a collection of information about its target, including its
  209. name and file ID, creation date, parent directory name and ID, and volume name
  210. and creation date.
  211.  
  212. By storing alias records, you can allow your users to create robust connections
  213. between files—--that is, connections that can survive the moving or renaming of
  214. one or both files. The Finder™ in system software version 7.0 stores an alias
  215. record when the user creates a desktop alias object. The Edition Manager uses
  216. alias records to implement data-sharing among separate documents. (The Finder
  217. Interface and Edition Manager chapters in this volume describe those features in
  218. detail. The section “Using the Alias Manager,” later in this chapter, describes
  219. how the Finder and the Edition Manager call the Alias Manager.)
  220.  
  221. The alias record itself contains two kinds of information: public information
  222. available to your application and private information used by the Alias Manager.
  223.  
  224. TYPE
  225. AliasHandle  =  ^AliasPtr;
  226. AliasPtr     =  ^AliasRecord;
  227. AliasRecord  =
  228.   RECORD
  229.     userType:   OSType;  /* application’s signature */
  230.     aliasSize:  Integer  /* record size when created */
  231.     {variable-length private data}
  232.   END;
  233.  
  234. Your application can use the userType field to store its own signature or any
  235. other data that fits in four bytes. When the Alias Manager fills in an alias
  236. record, it stores four spaces (0x20202020) in that field.
  237.  
  238. The Alias Manager stores the size of the record when it was created in the
  239. aliasSize field. Knowing the starting size allows your application to store and
  240. retrieve data of its own at the end of the record. First, expand the size of the
  241. record with the Memory Manager, described in Volume II. You can then find the
  242. starting address of your own data in the record by adding the record’s starting
  243. address to its original length, as reported in the aliasSize field.
  244.  
  245. The private Alias Manager data includes a collection of file, directory, and
  246. volume names and their creation dates; file and directory IDs; a full pathname,
  247. including the volume name; and, if applicable, AppleShare information for use in
  248. resolving the alias record.
  249.  
  250. When you create an alias record, you have the option of recording a relative
  251. path, that is, the path to the target object from another file or folder on the
  252. same disk. The beginning point of a relative path is called the fromFile. To
  253. record relative path, the Alias Manager saves the distances from the target and
  254. the fromFile to the common parent, that is, the lowest-level directory that
  255. appears in the pathnames of both. The Alias Manager can later use those
  256. distances in conjunction with the absolute pathname to conduct a relative
  257. search.
  258.  
  259. Suppose, for example, that you are writing a word-processing application that
  260. allows the user to build a customized, supplemental dictionary for each
  261. document. You create the dictionary as a separate document in the same folder as
  262. the document it serves, as Figure 24-1 shows.
  263.  
  264. ø 24.1  Recording of Relative Path
  265.  
  266. When resolving the alias record using relative path, the Alias Manager starts at
  267. the directory the specified distance above the fromFile, the directory named
  268. Sample in the example above. The Alias Manager then constructs a pathname by
  269. using one field of the absolute pathname for each step from the target to the
  270. common parent. In this example, the distance is one, so the pathname contains
  271. only the name of the target document, Dictionary.
  272.  
  273. In some circumstances, a relative search identifies the correct target when an
  274. absolute search could not. For example, suppose the user of your word-processing
  275. application creates a working copy of a document and dictionary by copying the
  276. entire folder Sample to another disk. The user later updates the original
  277. document and dictionary by copying the folder from the working disk. All of the
  278. underlying file and folder identifications change, but the filenames and
  279. relative path remain the same. When the user later runs the spelling checker on
  280. the document, a relative-path search finds the target dictionary.
  281.  
  282. The Alias Manager accepts and returns file specifications only in the form of
  283. file system specification records (FSSpec records), described in the File
  284. Manager chapter of this volume. The FSSpec record represents the simlest
  285. complete description of a file system object. It contains a volume reference
  286. number, a parent directory ID, and a name.
  287.  
  288. _______________________________________________________________________________
  289.  
  290. æKY Strategies…for…Resolving…Alias…Records
  291. æC »STRATEGIES FOR RESOLVING ALIAS RECORDS                                   Alias Manager
  292. _______________________________________________________________________________
  293.  
  294. The Alias Manager provides three alias-resolution functions:
  295.  
  296.   •   The high-level function ResolveAlias performs a fast search for a single
  297.       target. If the target resides on an unmounted volume, ResolveAlias
  298.       attempts to mount the volume automatically. If it finds no match for the
  299.       alias record, ResolveAlias simply returns an error code.
  300.  
  301.   •   The high-level function SelectAlias can identify more than one possible
  302.       target. If it identifies either no targets or more than one possible
  303.       target, it displays a dialog box, through which the user can direct the
  304.       search. SelectAlias starts with a fast search and can perform a slow
  305.       search at the user’s request. (Fast and slow searches are described
  306.       below.) If the target resides on an unmounted volume, SelectAlias
  307.       attempts to mount the volume automatically.
  308.  
  309.   •   The low-level function MatchAlias accepts a set of input rules to control
  310.       the search. MatchAlias can perform either a fast or a slow search. It can
  311.       identify and return multiple possible targets. Your program must process
  312.       the results.
  313.  
  314. The following sections describe the fast- and slow-search algorithms the Alias
  315. Manager uses to resolve alias records. For information on using the functions,
  316. see “Using the Alias Manager” and “Alias Manager Routines” later in this
  317. chapter.
  318.  
  319. _______________________________________________________________________________
  320.  
  321. æKY Fast…Search
  322. æC »Fast Search                                                              Alias Manager
  323. _______________________________________________________________________________
  324.  
  325. The fast-search algorithm is designed to find the most likely match for an alias
  326. record first. This strategy meets the needs of the ResolveAlias function, which
  327. exits as soon as it finds one match. The fast-search algorithm can, however,
  328. identify more than one possible target for presentation to the user through the
  329. SelectAlias function.
  330.  
  331. The first step in the search is to identify the volume on which the target
  332. resides, using the volume’s name, creation date (which acts almost as a unique
  333. identifier for a volume), and volume type (for example, a hard disk, a 3.5-inch
  334. disk, or an AppleShare volume).
  335.  
  336. The Alias Manager first looks for a volume by both name and creation date. The
  337. search succeeds if the volume is mounted and if its name and creation date have
  338. not changed since the record was created. If the target is on an unmounted
  339. AppleShare volume, the Alias Manager attempts to mount the volume. If the target
  340. is on an unmounted ejectable disk, the Alias Manager presents the switch-disk
  341. dialog box, illustrated in Figure 24-2.
  342.  
  343. ø 24.2  Switch-Disk Dialog Box
  344.  
  345. If the target volume is not found by name and creation date, the Alias Manager
  346. attempts to match by creation date only. This step locates volumes that have
  347. been renamed. Finally, the Alias Manager attempts to match by volume name only.
  348.  
  349. If none of these strategies results in a volume match, the Alias Manager returns
  350. nvsErr.
  351.  
  352. Once the target volume is identified, fast search looks for the actual target,
  353. first by file ID (if the target is a file) or directory ID (if the target is a
  354. volume or directory). (File IDs are described in the File Manager chapter of
  355. this volume.) Even if a file has been renamed or moved on a volume, the File
  356. Manager can find it quickly through its file ID.
  357.  
  358. If the search by file ID or directory ID fails, fast search looks for the target
  359. by name in the original parent directory. This search locates the target if its
  360. file or directory ID has changed but it still exists by the same name in the
  361. parent directory (for example, if the target was restored from backup). Fast
  362. search compares file numbers on files found by name in the correct parent
  363. directory. If the file numbers do not match, the file is treated as a possible
  364. match, that is, it is put on the list of candidates and the search continues. If
  365. the target is not found by name in the parent directory, fast search looks for a
  366. file by file number in the parent directory.
  367.  
  368. If the search by file ID or directory ID fails, and if fast search cannot find
  369. the original parent directory, it searches for the target by full pathname. This
  370. search finds the target if it resides in the same location on the disk but the
  371. directory ID of its parent directory has changed (for example, if the entire
  372. parent directory was backed up and restored).
  373.  
  374. If the full pathname fails, fast search attempts to find the file by tracing
  375. partial pathnames up through all parent folders, using parent directory IDs
  376. instead of folder names. For example, consider this full pathname:
  377.  
  378. MyDisk:MyReports:January:Sales Report
  379.  
  380. If the search by full pathname fails, fast search first looks for the partial
  381. pathname Sales Report in the directory MyDisk:MyReports:January. If that search
  382. fails, it looks for January:Sales Report in the directory MyDisk:MyReports, and
  383. so on.
  384.  
  385. If the search by absolute pathname fails, and if your application requests a
  386. relative search, fast search performs a relative search. (For a description of
  387. relative path, see “About Alias Records” earlier in this chapter.) The search
  388. succeeds if the relative path is the same as when the record was created and if
  389. the names of the objects have not changed.
  390.  
  391. _______________________________________________________________________________
  392.  
  393. æKY Slow…Search
  394. æC »Slow Search                                                              Alias Manager
  395. _______________________________________________________________________________
  396.  
  397. The slow-search algorithm uses the same strategy as fast search for identifying
  398. the volume.
  399.  
  400. Once the volume is identified, slow search calls the File Manager function
  401. PBCatSearch, searching for objects with a matching creation date, creator, and
  402. type. (See the File Manager chapter for a description of PBCatSearch.) It
  403. searches the entire volume.
  404.  
  405. PBCatSearch is available only on Hierarchical File System (HFS) volumes, not on
  406. Macintosh File System (MFS) volumes. (See the File Manager chapter of this
  407. volume for a description of the two file systems.) PBCatSearch is also available
  408. only on systems running version 7.0 and later. When searching an MFS volume or a
  409. volume on a file server running older system software, slow search performs a
  410. recursive search of the entire volume, searching for objects with matching
  411. creation date, type, creator, or file number.
  412.  
  413. _______________________________________________________________________________
  414.  
  415. æKY Using…the…Alias…Manager
  416. æC »USING THE ALIAS MANAGER                                                  Alias Manager
  417. _______________________________________________________________________________
  418.  
  419. You use the Alias Manager primarily to create and resolve alias records. You can
  420. also use it to look at and update alias records.
  421.  
  422. The Alias Manager creates an alias record in memory and provides you with a
  423. handle to the record. Your application can store the records on disk as
  424. resources of type 'alis' (see “Creating and Updating Alias Records”). When you
  425. no longer need the record in memory, call the DisposHandle procedure, described
  426. in the Memory Manager chapter of Volume II, to free the memory occupied by the
  427. record.
  428.  
  429. All Alias Manager routines accept and return file specifications only in the
  430. form of FSSpec records, which contain a volume reference number, a parent
  431. directory ID, and a target name. Use the File Manager function MakeFSSpec to
  432. convert other forms of file identification, such as pathname, into a canonical
  433. file specification (see the File Manager chapter in this volume for a
  434. description of file identification conventions).
  435.  
  436. For more detailed descriptions of the functions described in this section, see 
  437. “Alias Manager Routines” later in this chapter.
  438.  
  439. _______________________________________________________________________________
  440.  
  441. æKY Creating…Alias…Records
  442. æC »Creating Alias Records                                                   Alias Manager
  443. _______________________________________________________________________________
  444.  
  445. You create a new alias record by calling the NewAlias function. NewAlias fills
  446. in the record and provides a handle to it. NewAlias always records a collection
  447. of information about the target, including the full pathname. You can request
  448. that it store relative path information as well by supplying a starting point
  449. for a relative search.
  450.  
  451. Call NewAlias when you want to store a file description for later use. For
  452. example, suppose you were writing a word-processing application that allows the
  453. user to customize a dictionary for use with a single text file. Your application
  454. stores the custom data in a separate file in the same folder as the document. As
  455. soon as you create the dictionary file, you call NewAlias to create an alias
  456. record for that file, including path information relative to the user’s text
  457. document:
  458.  
  459. MyErr  := NewAlias(textFilePtr, targetPtr, myAliasHdl);
  460.  
  461. The parameter textFilePtr is a pointer to a FSSpec record that identifies the
  462. starting point for the relative search, in this case the user’s text file. If
  463. you do not want relative path information recorded, pass a value of NIL in the
  464. first parameter.
  465.  
  466. The parameter targetPtr is a pointer to a FSSpec record that identifies the
  467. target file, in this example the dictionary file.
  468.  
  469. The parameter myAliasHdl a variable in which the Alias Manager returns a handle
  470. to the target description.
  471.  
  472. _______________________________________________________________________________
  473.  
  474. æKY Resolving…Alias…Records
  475. æC »Resolving Alias Records                                                  Alias Manager
  476. _______________________________________________________________________________
  477.  
  478. The Alias Manager provides three alias-resolution functions:
  479.  
  480.   •   ResolveAlias, which simply searches for one target and exits if it fails
  481.  
  482.   •   SelectAlias, which searches for all plausible targets and displays a
  483.       dialog box to the user if it finds either more than one target or no
  484.       targets
  485.  
  486.   •   MatchAlias, which returns one or more targets
  487.  
  488. ResolveAlias and SelectAlias are both high-level functions, which call the
  489. low-level function MatchAlias. The sections below describe the three functions
  490. in detail. The section “Strategies for Resolving Alias Records,” earlier in this
  491. chapter, describes the underlying search strategies used by the alias-resolution
  492. functions.
  493.  
  494. In general, when you want to identify only the single most likely target of an
  495. alias record, you call ResolveAlias. When you want the user to guide the
  496. resolution of any ambiguous records, you call SelectAlias. When you want your
  497. program to control the search or branch depending on the outcome, you call
  498. MatchAlias.
  499.  
  500. For example, the Finder stores a single alias record for each alias object that
  501. appears on the desktop. When the user opens an alias from the Finder, the Finder
  502. identifies the real object to be opened by resolving the alias record before it
  503. starts up the appropriate application. The Finder calls the ResolveAlias
  504. function, which either finds the target or exits.
  505.  
  506. The Edition Manager follows a more complicated strategy, designed to shield the
  507. user from dialog boxes until they are necessary. Applications can use the
  508. Edition Manager to allow users to incorporate information from one document into
  509. another. When the user inserts shared data into a document, the Edition Manager
  510. stores an alias record that points to the edition, that is, the file that
  511. contains the shared data. Figure 24-3 illustrates how an alias record in a user
  512. document points to an edition.
  513.  
  514. ø 24.3  How the Edition Manager Uses an Alias Record
  515.  
  516. When the user opens a document that includes one or more sections of shared
  517. data, the Edition Manager first checks to see if any of the shared data is out
  518. of date. It then makes a quick attempt to resolve the alias records for all
  519. sections that need to be updated. It calls MatchAlias for each record,
  520. requesting a fast search with automatic mounting suppressed and a maximum of two
  521. matches. If MatchAlias finds only one match for a record, the Edition Manager
  522. accepts that candidate as the correct target. If MatchAlias finds no matches or
  523. two matches, the Edition Manager simply tags that record as unresolved. When the
  524. user tries to display or print a portion of the document that contains an
  525. unresolved record, the Edition Manager calls SelectAlias, which either finder
  526. the target or prompts the user to direct the search for the correct target. This
  527. strategy provides automatic resolution of unambiguous alias records, allows the
  528. user to resolve ambiguities, and delays alias-resolution dialogs until they are
  529. really necessary.
  530.  
  531. _______________________________________________________________________________
  532.  
  533. æKY ResolveAlias
  534. æC »ResolveAlias                                                             Alias Manager
  535. _______________________________________________________________________________
  536.  
  537. In the simplest case, you can call the ResolveAlias function to resolve an alias
  538. record. ResolveAlias performs a fast search (described in “Strategies for
  539. Resolving Alias Records”) and exits after it identifies one target.
  540.  
  541. ResolveAlias compares some key information about the identified target with the
  542. information stored in the alias record. If any of the information is different,
  543. ResolveAlias automatically updates the record.
  544.  
  545. In the dictionary example, illustrated in Figure 24-1, above, the application
  546. calls ResolveAlias when the user runs the spelling-checker on an application
  547. with a customized dictionary.
  548.  
  549. MyErr := ResolveAlias(textFilePtr, myAliasHdl, targetPtr, updateFlag);
  550.  
  551. The parameter textFilePtr is a pointer to a FSSpec record that identifies the
  552. starting point for the relative search, in this case the user’s text file. If
  553. you do not want relative path information used in the search, pass a value of
  554. NIL in the first parameter.
  555.  
  556. The parameter myAliasHdl points to the alias record to be resolved. In this
  557. example, the alias record describes the dictionary file.
  558.  
  559. The parameter targetPtr is a is a pointer to the FSSpec record where the Alias
  560. Manager will place the results of its search. After ResolveAlias completes, the
  561. record pointed to by targetPtr contains the specification for the dictionary
  562. file.
  563.  
  564. The ResolveAlias function uses the updateFlag parameter to report whether or not
  565. it updated the alias record. After ResolveAlias completes, updateFlag is TRUE if
  566. the record was updated and FALSE if it was not.
  567.  
  568. _______________________________________________________________________________
  569.  
  570. æKY SelectAlias
  571. æC »SelectAlias                                                              Alias Manager
  572. _______________________________________________________________________________
  573.  
  574. If you want to let the user handle any ambiguities in the resolution, you can
  575. call the SelectAlias function to resolve an alias.
  576.  
  577. The SelectAlias function always performs a fast search first. If the search
  578. identifies only one target, it behaves exactly like ResolveAlias. If the search
  579. identifies no targets or more than one possible target, the Alias Manager
  580. presents a dialog box like the one in Figure 24-4.
  581.  
  582. ø 24.4  SelectAlias dialog box
  583.  
  584. In this example, the user moved the original target file, Sales Report, to a
  585. different folder. Later, the user copied the file back into its original parent
  586. folder and renamed the original file, now in a different folder, Old Sales
  587. Report. The Sales Report file now appears in the correct parent directory with
  588. the correct name but a different file ID. The file Old Sales Report appears in a
  589. different parent directory with a different name but with the original file ID.
  590. The fast-search algorithm identifies both files as possible targets.
  591.  
  592. The first field in the dialog box informs the user of the ambiguity. The message
  593. is fixed except for the name of the target and the type description, which is
  594. the word immediately before the target name (Edition in this example). You can
  595. control the type description through the fileTypeName parameter in the
  596. SelectAlias function. If you pass an empty string in this parameter, the Alias
  597. Manager substitutes the word document or folder, depending on what kind of
  598. object the alias describes. The name of the target is the original filename
  599. stored in the alias record.
  600.  
  601. The left scroll list, labeled “Name:”, shows the names of all possible alias
  602. matches. The first entry is highlighted when the dialog box first appears.
  603.  
  604. The right scroll list, labeled “Location:”, displays the full path of whatever
  605. entry is highlighted in the Name column. Entries in this list are not
  606. selectable.
  607.  
  608. The Select button accepts the highlighted entry as the target of the alias
  609. record. When the user clicks Select, SelectAlias removes the dialog box and
  610. places the highlighted entry in the target parameter. Pressing the Enter or
  611. Return key or double-clicking an entry in the name list has the same effect as
  612. clicking Select.
  613.  
  614. The Cancel button cancels the entire selection process. When the user clicks
  615. Cancel, SelectAlias removes the dialog box and returns userCanceledErr. Pressing
  616. the Esc (Escape) key or Command-period has the same effect as clicking Cancel.
  617.  
  618. The Try Harder button triggers an asynchronous slow search of all mounted
  619. volumes, beginning, if possible, with the volume on which the target resided
  620. when the alias record was last updated. If the slow search identifies additional
  621. possible matches, the Alias Manager adds them to the name list. If the slow
  622. search takes more than three seconds in real time, the Alias Manager presents a
  623. dialog box that allows the user to cancel the search in progress. Once the Alias
  624. Manager has completed the slow search, it dims the Try Harder button.
  625.  
  626. The Another One button lets the user override the entire selection process. The
  627. Alias Manager presents a dialog box much like the Standard File Package dialog
  628. box, which allows the user to select any file or folder on the system. Clicking
  629. OK accepts the highlighted object as the target of the search. While this dialog
  630. box is on the screen, clicking Cancel returns the user to the SelectAlias dialog
  631. box.
  632.  
  633. In the dictionary example described above, the application could call
  634. SelectAlias instead of ResolveAlias so that the user can help locate the correct
  635. dictionary if a fast search fails to find it.
  636.  
  637. MyErr := SelectAlias(textFilePtr, typeStr, NIL, myAliasHdl, targetPtr,
  638.          updateFlag, NIL, NIL);
  639.  
  640. The parameter textFilePtr is a pointer to a FSSpec record that identifies the
  641. starting point for the relative search, in this case the user’s text file. If
  642. you do not want relative path information used in the search, pass a value of
  643. NIL in the first parameter.
  644.  
  645. The parameter typeStr points to a string containing the word Dictionary. When
  646. SelectAlias displays its dialog box, it uses this string to remind the user that
  647. the target is a dictionary file.
  648.  
  649. The first NIL parameter tells SelectAlias that the application is not supplying
  650. a filter function to process the results of the search.
  651.  
  652. The parameter myAliasHdl points to the alias record to be resolved. In this
  653. example, the alias record describes the dictionary file.
  654.  
  655. The parameter targetPtr is a is a pointer to the FSSpec record where the Alias
  656. Manager will place the results of its search. After SelectAlias completes, the
  657. record pointed to by targetPtr contains the specification for the dictionary
  658. file.
  659.  
  660. The SelectAlias function uses the updateFlag parameter to report whether or not
  661. it updated the alias record. After SelectAlias completes, updateFlag is TRUE if
  662. the record was updated and FALSE if it was not.
  663.  
  664. The second NIL parameter controls the filtering of events by the ModalDialog
  665. procedure while the SelectAlias dialog box is on the screen. A value of NIL
  666. means that your application does no special filtering. (SelectAlias calls
  667. ModalDialog when it displays the SelectAlias dialog box. For a description of
  668. the ModalDialog procedure, see the Dialog Manager chapter of Volume I.) Because
  669. this example does not provide a custom filter function, it does not need to pass
  670. any data of its own, and it sets the final parameter to NIL.
  671.  
  672. _______________________________________________________________________________
  673.  
  674. æKY MatchAlias
  675. æC »MatchAlias                                                               Alias Manager
  676. _______________________________________________________________________________
  677.  
  678. The MatchAlias function is a low-level routine that gives your program control
  679. over the searching algorithm.
  680.  
  681. You can control the search by setting flags in the rulesMask parameter. The
  682. flags let you specify whether to attempt an automatic mounting of unmounted
  683. volumes; whether to search on more than one volume; and whether to perform a
  684. fast search, a slow search, or both. (For details about the rulesMask parameter,
  685. see “Alias Manager Routines” later in this chapter.) You can also specify a
  686. maximum number of candidates to be identified.
  687.  
  688. MatchAlias returns all candidates that it identifies in an array of FSSpec
  689. records.
  690.  
  691. You can use MatchAlias to perform a preliminary search for a target, branching
  692. to different routines depending on the outcome. The Edition Manager calls
  693. MatchAlias, as described in the introduction to this section, “Resolving Alias
  694. Records.”
  695. _______________________________________________________________________________
  696.  
  697. æKY Reading…Alias…Records
  698. æC »Reading Alias Records                                                    Alias Manager
  699. _______________________________________________________________________________
  700.  
  701. To retrieve information from an alias record without actually resolving the
  702. record, call the GetAliasInfo function. You can use GetAliasInfo to retrieve the
  703. name of the target, the names of its parent directories, the name of its volume,
  704. or, in the case of an AppleShare volume, the zone or server name.
  705.  
  706. _______________________________________________________________________________
  707.  
  708. æKY Maintaining…Alias…Records
  709. æC »Maintaining Alias Records                                                Alias Manager
  710. _______________________________________________________________________________
  711.  
  712. To update an alias record, call the UpdateAlias function. You can use
  713. UpdateAlias any time you know that the target of an alias record has been
  714. renamed or otherwise changed.
  715.  
  716. You are most likely to call UpdateAlias after a call to the MatchAlias function.
  717. If MatchAlias identifies a single target, it sets a flag telling you whether or
  718. not the key information about the target file matches the information in the
  719. alias record. It is the responsibility of your application to update the record.
  720.  
  721. The ResolveAlias and SelectAlias functions automatically update an alias record
  722. when the key information about the target they return does not match the record.
  723.  
  724. _______________________________________________________________________________
  725.  
  726. æKY Storing…and…Retrieving…Alias…Records
  727. æC »Storing and Retrieving Alias Records                                     Alias Manager
  728. _______________________________________________________________________________
  729.  
  730. Alias records are stored as resources of type 'alis'.
  731.  
  732. CONST  rAliasType = 'alis'
  733.  
  734. To store and retrieve alias records, use the standard Resource Manager functions
  735. described in the Resource Manager chapter of Volume I.
  736.  
  737. _______________________________________________________________________________
  738.  
  739. æKY Alias…Manager…Routines
  740. æC »ALIAS MANAGER ROUTINES                                                   Alias Manager
  741. _______________________________________________________________________________
  742.  
  743. This section describes the routines you use to create, update, read, and resolve
  744. alias records.
  745.  
  746. All Alias Manager routines use file system specification records (FSSpec
  747. records) to identify files, folders, and volumes. To create a FSSpec record,
  748. call the function MakeFSSpec, described in the File Manager chapter of this
  749. volume.
  750.  
  751. The Alias Manager routines can return the result codes listed in this section or
  752. any other applicable file system or memory management result codes. The file
  753. system result codes are listed in the File Manager chapter of Volume IV, and the
  754. memory management result codes are listed in the Memory Manager chapter of this
  755. volume.
  756.  
  757. _______________________________________________________________________________
  758.  
  759. æKY Creating…and…Updating…Alias…Records
  760. æC »Creating and Updating Alias Records                                      Alias Manager
  761. _______________________________________________________________________________
  762.  
  763. You use the NewAlias function to create an alias record.
  764.  
  765. FUNCTION NewAlias (fromFile,target: FSSpecPtr; VAR alias: AliasHandle) : OSErr;
  766.  
  767. NewAlias creates an alias record that describes the object specified in the
  768. target parameter. It fills in the record and puts a record handle in the alias
  769. parameter.
  770.  
  771. The fromFile parameter represents the starting point for a relative search. This
  772. parameter can be either NIL or a pointer to a valid FSSpec record. If fromFile
  773. is NIL, the alias record does not include relative path information. Specify a
  774. value for fromFile only if you want NewAlias to record relative path
  775. information.
  776.  
  777. The target parameter points to a FSSpec record for the file, folder, or volume
  778. to be described by the alias record.
  779.  
  780. The alias parameter is the handle for the newly created alias record. If the
  781. function fails to create an alias record, it sets alias to NIL.
  782.  
  783. Result codes
  784. paramErr  -50  The target parameter is NIL
  785.  
  786.  
  787. You use the UpdateAlias function to update an alias record.
  788.  
  789. FUNCTION UpdateAlias (fromFile,target: FSSpecPtr; alias: AliasHandle; VAR 
  790.                       wasChanged: Boolean) : OSErr;
  791.  
  792. UpdateAlias updates the alias record pointed to by the alias parameter so that
  793. it describes the file, folder, or volume specified by the target parameter.
  794. UpdateAlias rebuilds the entire alias record.
  795.  
  796. The fromFile parameter represents the starting point for a relative search. This
  797. parameter can be either NIL or a pointer to a valid FSSpec record. If fromFile
  798. is NIL, the updated alias record does not include relative path information.
  799. Specify a value for fromFile only if you want UpdateAlias to record relative
  800. path information.
  801.  
  802. The target parameter is the target of the alias record. This parameter must
  803. point to a valid canonical file specification record.
  804.  
  805. The alias parameter points to the alias record to be updated.
  806.  
  807. If the newly constructed alias record is exactly the same as the old one,
  808. UpdateAlias sets the wasChanged parameter to FALSE. Otherwise, it sets it to
  809. TRUE. Check this parameter to determine whether you need to save an updated
  810. record.
  811.  
  812. Result codes
  813. paramErr  -50  target, alias, or both are NIL, or the handle is corrupt
  814. _______________________________________________________________________________
  815.  
  816. æKY Resolving…and…Reading…Records
  817. æC »Resolving and Reading Records                                            Alias Manager
  818. _______________________________________________________________________________
  819.  
  820. You use the ResolveAlias function to resolve an alias. 
  821.  
  822. FUNCTION ResolveAlias (fromFile: FSSpecPtr; alias: AliasHandle; VAR target: 
  823.                        FSSpec; VAR wasChanged: Boolean) : OSErr;
  824.  
  825. If the resolution is successful, ResolveAlias returns the FSSpec record for the
  826. target filename through the target parameter, updates the alias record if
  827. necessary, and reports whether or not the record was updated through the
  828. wasChanged parameter. If the target object is on an unmounted AppleShare volume,
  829. ResolveAlias automatically mounts the volume. If the target is on an unmounted,
  830. ejectable volume, ResolveAlias displays a switch-disk dialog box. ResolveAlias
  831. exits after it finds one acceptable target.
  832.  
  833. The fromFile parameter represents the starting point for a relative search. This
  834. parameter can be either NIL or a valid FSSpec record. If fromFile is NIL,
  835. ResolveAlias does not perform a relative sesarch.
  836.  
  837. The alias parameter points to the alias record to be resolved and, if necessary,
  838. updated.
  839.  
  840. The Target parameter receives the FSSpec record of the target filename.
  841.  
  842. If it updates the alias record, ResolveAlias sets the wasChanged parameter to
  843. TRUE. Otherwise, it sets it to FALSE. If the function returns an error code, it
  844. sets wasChanged to FALSE.
  845.  
  846. Result codes
  847. nsvErr    -35  The volume is not mounted
  848. fnfErr    -43  No target was found
  849. paramErr  -50  The alias parameter is NIL, or the handle is corrupt
  850.  
  851.  
  852. If you want the user to direct the search when an alias record cannot be
  853. resolved unambiguously, call the SelectAlias function.
  854.  
  855. FUNCTION SelectAlias (fromFile: FSSpecPtr; fileTypeName: Str31; aliasFilter: 
  856.                       ProcPtr; alias: AliasHandle; VAR target: FSSpec; VAR 
  857.                       wasChanged: Boolean; filterProc: ProcPtr; callbackPtr:
  858.                       Ptr) : OSErr;
  859.  
  860. If SelectAlias finds a single match for the record pointed to by the alias
  861. parameter, it behaves the same way as ResolveAlias. If SelectAlias finds no
  862. matches or more than one match for the record, the Alias Manager presents a
  863. modal dialog box that allows the user to direct the search and select the
  864. target. (See “User-Directed Search” for a description of the dialog box.)
  865.  
  866. The fromFile parameter represents the starting point for a relative search. This
  867. parameter can be either NIL or a valid FSSpec. If fromFile is NIL, SelectAlias
  868. does not perform a relative search.
  869.  
  870. The fileTypeName string is a descriptive name for the file type of the target
  871. object, intended to help the user select the correct target. It appears as part
  872. of the title of the dialog box.
  873.  
  874. The aliasFilter parameter points to an optional filter function supplied by your
  875. application. The Alias Manager executes this function for each possible match
  876. that SelectAlias finds or after three seconds have elapsed without  a match.
  877. Your filter function returns a Boolean value that determines whether the
  878. possible match is to be discarded (TRUE) or displayed (FALSE). It can also
  879. terminate the search. The function has three parameters.
  880.  
  881.    FUNCTION MySelectAliasFilter (paramBlock: CInfoPBPtr; VAR quitFlag: Boolean; 
  882.                                  callbackPtr: Ptr) : Boolean
  883.  
  884.   The paramBlock parameter points to the catalog information parameter block    
  885.   record (as returned by the File Manager function PBGetCatInfo) of the alias 
  886.   match. The Alias Manager sets this parameter to NIL if it is calling the 
  887.   function to give it the chance to terminate the search. (Do not use this 
  888.   pointer without checking for NIL.) Your filter function sets the quitFlag 
  889.   parameter to terminate the search.
  890.  
  891.   The callbackPtr parameter is the same as the SelectAlias input parameter   
  892.   callbackPtr. This parameter allows your filter function to access your global 
  893.   or local data.
  894.  
  895.  
  896. The alias parameter points to the alias record to be resolved and, if 
  897. necessary, updated.
  898.  
  899. After the alias is resolved to a single target, the target parameter receives
  900. the FSSpec for the target.
  901.  
  902. If it updates the alias record, SelectAlias sets the wasChanged parameter to
  903. TRUE. Otherwise, it sets it to FALSE. If the function returns an error code, it
  904. sets wasChanged to FALSE.
  905.  
  906. The filterProc parameter points to your application’s optional event-filtering
  907. function, to be called by ModalDialog. (SelectAlias calls ModalDialog when it
  908. displays the SelectAlias dialog box. For a description of the ModalDialog
  909. procedure, see the Dialog Manager chapter of Volume I.) The filterProc parameter
  910. is similar to the same parameter in the Standard File Package procedure
  911. SFPGetFile. The function pointed to by filterProc must be the same as the one
  912. you would pass directly to ModalDialog in its filterProc parameter, except that
  913. it takes an additional fourth argument, which is the callbackPtr parameter as
  914. passed to the SelectAlias routine. This option allows your filter function to
  915. access the value of callbackPtr to retrieve your data.
  916.  
  917. The callbackPtr parameter contains whatever data you specify. Use this parameter
  918. to pass information to your filter function.
  919.  
  920. Result codes
  921. fnfErr            -43  No target was found
  922. paramErr          -50  target, alias, or both are NIL, or the handle is corrupt
  923. userCanceledErr  -128  The user canceled the operation
  924.  
  925. You use the MatchAlias function to identify a list of possible matches and pass
  926. the list through a selection filter. The filter can pass more than one possible
  927. match.
  928.  
  929. FUNCTION MatchAlias (fromFile: FSSpecPtr; rulesMask: LongInt; alias:
  930. AliasHandle;   
  931.                      VAR aliasCount: Integer; aliasList: FSSpecListPtr; VAR
  932.                      needsUpdate: Boolean; aliasFilter: ProcPtr; callbackPtr:
  933.                      Ptr) : OSErr;
  934.  
  935. MatchAlias resolves the alias record pointed to by the alias parameter and
  936. returns a list of FSSpec records in the structure pointed to by the aliasList
  937. parameter. If it identifies more than one possible target, MatchAlias places in
  938. the aliasCount parameter the number of candidates in aliasList. MatchAlias
  939. follows the rules specified by the rulesMask parameter. If it resolves the alias
  940. to an object other than the one stored in the alias record or if it returns a
  941. list of possible candidates, it sets the needsUpdate flag to TRUE. Your
  942. application is responsible for calling UpdateAlias if necessary after the target
  943. is identified.
  944.  
  945. The fromFile parameter represents the starting point for a relative search. This
  946. parameter can be either NIL or a valid FSSpec record. If fromFile is NIL,
  947. MatchAlias does not perform a relative search.
  948.  
  949. The rulesMask parameter specifies a set of rules to guide the resolution. Pass
  950. the sum of all of the rules you want to invoke.
  951.  
  952. Constant        Description
  953.  
  954. kARMmountVol    Automatically try to mount the target’s volume if it is not    
  955.                 mounted.  If this rule is not set, and if the target’s volume is
  956.  
  957.                 not mounted, MatchAlias returns nsvErr.
  958.  
  959. kARMmultVols    Search all mounted volumes. The search begins with the volume on
  960.  
  961.                 which the target resided when the record was created.
  962.  
  963. kARMsearch      Search quickly for the alias, using the fast-search algorithm.
  964.  
  965. kARMsearchMore  Search further, using the slow-search algorithm.
  966.  
  967.                 The further search uses the File Manager function CatSearch to
  968.                 match criteria such as creation date, type, and creator.
  969.                 CatSearch is available only on HFS volumes. When searching MFS
  970.                 volumes or AppleShare volumes running older system software, 
  971.                 MatchAlias performs a recursive, indexing search using creation 
  972.                 date, type, and creator.
  973.  
  974.                 If both kARMsearch and kARMsearchMore are set, MatchAlias 
  975.                 performs a fast search followed by a slow search.
  976.  
  977. The alias parameter points to the alias record to be resolved.
  978.  
  979. Your application can specify a maximum number of possible matches by setting the
  980. aliasCount parameter. MatchAlias sets the aliasCount parameter to the number of
  981. entries in the list of possible matches.
  982.  
  983. The aliasList parameter points to the array that holds the results of the
  984. search.
  985.  
  986. If MatchAlias resolves the alias to a target whose key information is different,
  987. or if it returns a list of possible candidates, it sets the needsUpdate flag to
  988. TRUE. Otherwise, it sets it to FALSE.
  989.  
  990. The aliasFilter parameter points to a filter function supplied by your
  991. application. The Alias Manager executes this function for each possible match
  992. that MatchAlias finds or after three seconds have elapsed without  a match. Your
  993. filter function returns a Boolean value that determines whether the possible
  994. match is discarded (TRUE) or added to the list of possible targets (FALSE). It
  995. can also terminate the search. The function has three parameters.
  996.  
  997.    FUNCTION MyMatchAliasFilter (paramBlock: CInfoPBPtr; VAR quitFlag: Boolean;  
  998.                                 callbackPtr: Ptr): Boolean
  999.    The paramBlock parameter points to the catalog information parameter block  
  1000.  
  1001.    record (as returned by the File Manager function PBGetCatInfo) of the alias 
  1002.    match. The Alias Manager sets this parameter to NIL if it is calling the 
  1003.    function to give it the chance to terminate the search. (Do not use this 
  1004.    pointer without checking for NIL.) Your filter function sets the quitFlag 
  1005.    parameter to terminate the search.
  1006.  
  1007.    The callbackPtr parameter is the same as the MatchAlias input parameter   
  1008.    callbackPtr. This parameter allows your filter function to access your global
  1009.  
  1010.    or local data.
  1011.  
  1012.  
  1013.    The callbackPtr parameter contains whatever data you specify. Use this 
  1014.    parameter to pass information to your filter function.
  1015.  
  1016. Result codes
  1017. nsvErr            -35  The volume is not mounted
  1018. fnfErr            -43  No target was found
  1019. paramErr          -50  target, alias, or both are NIL, or the handle is corrupt
  1020. userCanceledErr  -128  The user canceled the operation
  1021.  
  1022.  
  1023. You can use the GetAliasInfo function to read information from an alias record.
  1024.  
  1025. FUNCTION GetAliasInfo (alias: AliasHandle; index: AliasInfoType; VAR theString:
  1026.                        Str63 ) : OSErr;
  1027.  
  1028. GetAliasInfo retrieves the information specified by the index parameter from the
  1029. record pointed to by the alias parameter and places it in the parameter
  1030. theString.
  1031.  
  1032. The alias parameter points to the alias record to be read.
  1033.  
  1034. The index parameter specifies the kind of information to be retrieved. If index
  1035. is a positive integer, GetAliasInfo retrieves the parent folder that has the
  1036. same hierarchical level as the index parameter. You can therefore assemble the
  1037. names of the target and all of its parent folders by making repeated calls to
  1038. GetAliasInfo with incrementing index values, starting with a value of 0. When
  1039. index is greater than the hierarchical level of the root, GetAliasInfo returns
  1040. an empty string. You can also set index to one of these five values:
  1041.  
  1042. Constant      Value  Description
  1043. asiZoneName    -3    If the record represents an object on an AppleShare volume,
  1044.  
  1045.                      retrieve the server’s zone name. Otherwise, return an empty
  1046.                      string.
  1047.  
  1048. asiServerName  -2    If the record represents an object on an AppleShare volume,
  1049.  
  1050.                      retrieve server name. Otherwise, return an empty string.
  1051.  
  1052. asiVolumeName  -1    Return the name of the volume on which the represented 
  1053.                      object resides.
  1054.  
  1055. asiAliasName    0    Return the name of the object represented by the record.
  1056.  
  1057. asiParentName   1    Return the name of the parent folder of the object 
  1058.                      represented by the record. If the object is a volume, 
  1059.                      return the volume name.
  1060.  
  1061. GetAliasInfo places the requested information in the parameter theString.
  1062.  
  1063. GetAliasInfo returns the information stored in the alias record, which might not
  1064. be current.
  1065.  
  1066. Result codes
  1067. paramErr  -50  alias, theString, or both are NIL; the index is less
  1068.                than asiZoneName; or the handle is corrupt
  1069. _______________________________________________________________________________
  1070.  
  1071. æKY Summary…of…the…Alias…Manager
  1072. æC »SUMMARY OF THE ALIAS MANAGER                                             Alias Manager
  1073. _______________________________________________________________________________
  1074.  
  1075. The following cards summarize the constants, data types, and routines for the
  1076. Alias Manager.
  1077. _______________________________________________________________________________
  1078.  
  1079. æKY Alias…Constants
  1080. æC »Constants                                                           Alias Manager
  1081. _______________________________________________________________________________
  1082.  
  1083. CONST
  1084. rAliasType  =  'alis';    {resource type for saved alias records}
  1085.  
  1086. {rulesMask for MatchAlias}
  1087. kARMmountVol    =  $0001;  {mount the volume automatically}
  1088. kARMmultVols    =  $0008;  {search on multiple volumes}
  1089. kARMsearch      =  $0100;  {search quickly}
  1090. kARMsearchMore  =  $0200;  {search further}
  1091.  
  1092. {index values for GetAliasInfo}
  1093. asiZoneName    =  -3;
  1094. asiServerName  =  -2;
  1095. asiVolumeName  =  -1;
  1096. asiAliasName   =   0;
  1097. asiParentName  =   1;
  1098. _______________________________________________________________________________
  1099.  
  1100. æKY Alias…Data…Types
  1101. æC »Data Types                                                               Alias Manager
  1102. _______________________________________________________________________________
  1103.  
  1104. TYPE
  1105. FSSpecArrayPtr  =  ^FSSpecArray;
  1106. FSSpecArray     =  ARRAY[0..0] OF FSSpec;
  1107.  
  1108. AliasHandle    =  ^AliasPtr;
  1109. AliasPtr       =  ^AliasRecord;
  1110. AliasRecord    =
  1111.   RECORD
  1112.     userType:  OSType;
  1113.     aliasSize:  Integer;
  1114.     {variable-length private data}
  1115.   END;
  1116. AliasInfoType  =  Integer;
  1117. _______________________________________________________________________________
  1118.  
  1119. æKY Alias…Routines
  1120. æC »Routines                                                                 Alias Manager
  1121. _______________________________________________________________________________
  1122.  
  1123. Creating and Updating Records
  1124.  
  1125. FUNCTION NewAlias (fromFile,target: FSSpecPtr; VAR alias: AliasHandle) : OSErr;
  1126. FUNCTION UpdateAlias (fromFile,target: FSSpecPtr; alias: AliasHandle; VAR 
  1127.                       wasChanged: Boolean) : OSErr;
  1128.  
  1129. Resolving and Reading Records
  1130.  
  1131. FUNCTION ResolveAlias (fromFile: FSSpecPtr; alias: AliasHandle; VAR target: 
  1132.                        FSSpec; VAR wasChanged: Boolean) : OSErr;
  1133. FUNCTION SelectAlias (fromFile: FSSpecPtr; fileTypeName: Str31; aliasFilter: 
  1134.                       ProcPtr; alias: AliasHandle; VAR target: FSSpec; VAR 
  1135.                       wasChanged: Boolean; filterProc: ProcPtr; callbackPtr:
  1136.                       Ptr) 
  1137.                       : OSErr;
  1138. FUNCTION MatchAlias (fromFile: FSSpecPtr; rulesMask: LongInt; alias:
  1139. AliasHandle; 
  1140.                      VAR aliasCount: Integer; aliasList: FSSpecListPtr; VAR 
  1141.                      needsUpdate: Boolean; aliasFilter: ProcPtr; callbackPtr: 
  1142.                      Ptr) : OSErr;
  1143. FUNCTION GetAliasInfo (alias: AliasHandle; index: AliasInfoType; VAR theString: 
  1144.                        Str63; ) : OSErr;
  1145. _______________________________________________________________________________
  1146.  
  1147. æKY Alias…Result…Codes
  1148. æC »Result Codes                                                             Alias Manager
  1149. _______________________________________________________________________________
  1150.  
  1151. nsvErr            -35  The volume is not mounted
  1152. fnfErr            -43  No target was found
  1153. paramErr          -50  One or more parameters is NIL, or a handle is corrupt
  1154. userCanceledErr  -128  The user canceled the operation
  1155. _______________________________________________________________________________
  1156.  
  1157. æKY Assembly-Language…Information…for…Alias
  1158. æC »Assembly-Language Information                                            Alias Manager
  1159. _______________________________________________________________________________
  1160.  
  1161. Constants
  1162.  
  1163. ;Resource type for alias records
  1164. rAliasType  .EQU  'alis'
  1165.  
  1166. ;rulesMask for MatchAlias
  1167. kARMmountVol    .EQU  $00000001;  {mount the volume automatically}
  1168. kARMmultVols    .EQU  $00000008;  {search on multiple volumes}
  1169. kARMsearch      .EQU  $00000100;  {search quickly}
  1170. kARMsearchMore  .EQU  $00000200;  {search further}
  1171.  
  1172. ;GetAliasInfo request types
  1173. asiZoneName    .EQU  -3  ;get zone name
  1174. asiServerName  .EQU  -2  ;get server name
  1175. asiVolumeName  .EQU  -1  ;get volume name
  1176. asiAliasName   .EQU   0  ;get object name
  1177. asiParentName  .EQU   1  ;get parent folder name
  1178.  
  1179. Alias Record Data Structure
  1180. userType               4 bytes      file type of target file
  1181. aliasSize              2 bytes      size of record in bytes
  1182. {variable-length private data}
  1183.  
  1184.  
  1185. _______________________________________________________________________________
  1186.  
  1187.  
  1188. æKY AppleDesktopBus
  1189. æC 
  1190. THE APPLE DESKTOP BUS
  1191. _______________________________________________________________________________
  1192.  
  1193. About…The…AppleDesktopBus…Chapter
  1194. About…the…Apple…Desktop…Bus
  1195. ADB…Manager…Routines
  1196. Writing…ADB…Device…Drivers
  1197. Summary…of…the…ADB
  1198. _______________________________________________________________________________
  1199.  
  1200.  
  1201.  
  1202. æKY About…The…AppleDesktopBus…Chapter
  1203. æC »ABOUT THIS CHAPTER                                        AppleDesktopBus
  1204. _______________________________________________________________________________
  1205.  
  1206. This chapter tells you how to accomplish low-level communication with peripheral
  1207. devices that are connected to the Apple Desktop Bus (ADB).
  1208.  
  1209. Reader’s guide:    The standard mouse and keyboard drivers automatically take
  1210.                    care of all required ADB access functions. When the user
  1211.                    manipulates the mouse or keyboard, the system calls the
  1212.                    appropriate driver and the application never uses the ADB
  1213.                    Manager. Hence you need the information in this chapter only
  1214.                    if you are writing a special driver, such as a driver for a
  1215.                    new user-input device.
  1216.  
  1217. The ADB is a simple local-area network that connects low-speed input-only devices to
  1218. the operating system. In the Macintosh II and Macintosh SE computers, the ADB is used
  1219. to communicate with one or more keyboards, the mouse, and other user input devices.
  1220.  
  1221. Keys located on multiple keyboards are distinguished by the keyboard event message,
  1222. as described in the Toolbox Event Manager chapter.
  1223.  
  1224. Note:  An ADB, using the same operating protocols, is also part of the
  1225.        Apple IIgs computer.
  1226.  
  1227. This chapter contains three principal sections:
  1228.  
  1229.   •  a description of the Apple Desktop Bus and how it works
  1230.   •  a description of the ADB Manager. This section of system ROM contains
  1231.      the routines that a driver must use to access devices connected to the ADB.
  1232.   •  a discussion of the special requirements for drivers that support
  1233.      devices connected to the ADB
  1234.  
  1235. You should already be familiar with
  1236.  
  1237.   •  the hardware interface to the Apple Desktop Bus, described in the
  1238.      Macintosh Family Hardware Reference
  1239.   •  events generated by ADB keyboard devices (described in the Toolbox
  1240.      Event Manager chapter) if your driver communicates with one or more
  1241.      keyboards
  1242.  
  1243. _______________________________________________________________________________
  1244.  
  1245.  
  1246. æKY About…the…Apple…Desktop…Bus
  1247. æC »ABOUT THE APPLE DESKTOP BUS                               AppleDesktopBus
  1248. _______________________________________________________________________________
  1249.  
  1250. The Apple Desktop Bus connects up to 16 low-speed input-only devices to the Macintosh
  1251. II or Macintosh SE computer. Each device can maintain up to four variable-size registers,
  1252. whose contents can be read from or written to by the ADB network. Each register may
  1253. contain from two to eight bytes. Two of the device registers have an assigned meaning
  1254. and a standardized format: register 0, used for interrupt information, and register
  1255. 3, containing the device’s identification number. The other two device registers have
  1256. no assigned meaning, and may have different meanings for read and write operations.
  1257.  
  1258. The system communicates with the Apple Desktop Bus through the system’s Versatile
  1259. Interface Adapter chip (VIA). The VIA is described in the Macintosh Hardware chapter.
  1260.  
  1261. Warning:  The ADB does not support connecting a device while the computer
  1262.           is running. The result may be to reinitialize all devices on the
  1263.           bus without informing the system.
  1264.  
  1265. The system always controls the bus. It issues commands to specific devices on the bus
  1266. and they respond by accepting data, sending data, or changing their configuration.
  1267. These commands are discussed below.
  1268.  
  1269. Note:  Devices connected to the ADB contain their own single-chip
  1270.        microprocessors, which handle both device routines and the
  1271.        ADB interface. If the system sends commands to a device with
  1272.        a duty cycle of more than 50%, the device’s microprocessor
  1273.        may become overloaded.
  1274.  
  1275. _______________________________________________________________________________
  1276.  
  1277. »Bus Commands
  1278.  
  1279. Each bus command consists of a byte that the system sends to a device connected to
  1280. the ADB. Applications may place bus commands on the network by calling the routine
  1281. ADBOp, discussed under “ADB Manager Routines” later in this chapter. There are four
  1282. bus commands; their bit layouts are shown in Figure 1.  All other bit layouts are
  1283. reserved.
  1284.  
  1285. •••Refer to Figure 1.•••
  1286.  
  1287. Figure 1–ADB Command Formats
  1288.  
  1289. The individual commands are discussed below.
  1290.  
  1291. Warning:  Values of the low bytes of the ADB command formats other than
  1292.           those shown in Figure 1 are reserved, and should not be used.
  1293.  
  1294. »SendReset
  1295.  
  1296. The SendReset command forces a hardware reset of all devices connected to the ADB.
  1297. Such a reset clears all pending device actions and places the devices in their startup
  1298. state. All devices are able to accept new ADB commands and user inputs immediately
  1299. thereafter. All devices ignore the high-order four bits of the SendReset command.
  1300.  
  1301. »Flush
  1302.  
  1303. The Flush command flushes data from the single device specified by the network address
  1304. in its high-order four bits. Network  addresses are discussed below, under “Device
  1305. Addressing”. It purges any pending user inputs and make the device ready to accept
  1306. new commands and input data.
  1307.  
  1308. »Listen
  1309.  
  1310. The Listen command is used to send instructions to devices connected to the ADB. It
  1311. transfers data from a buffer in system RAM to a register in the device specified by
  1312. the network address in its high-order four bits. The device register is specified by
  1313. the low-order two bits of the Listen command.
  1314.  
  1315. »Talk
  1316.  
  1317. The Talk command is used to fetch user inputs from devices connected to the ADB. It
  1318. is the complement of the Listen command. It transfers data from a register in the
  1319. device specified by the network address in its high-order four bits to a buffer in
  1320. system RAM. The device register is specified by the low-order two bits of the Talk
  1321. command.
  1322.  
  1323. _______________________________________________________________________________
  1324.  
  1325. »Device Registers
  1326.  
  1327. Each device connected to the ADB contains four registers, each of which may store
  1328. from two to eight bytes of data. Each register is identified by the value of the
  1329. low-order two bits in a Listen or Talk command. Registers 0 and 3 have dedicated
  1330. functions; registers 1 and 2 are used for purposes specific to each device, and need
  1331. not be present in a device.
  1332.  
  1333. Note:  ADB device registers are virtual registers; they need not be
  1334.        implemented physically.  The device firmware must only respond
  1335.        to register commands as if a register were present.
  1336.  
  1337. »Register 0
  1338.  
  1339. Device register 0 is reserved for input data. If the device has user-input data to be
  1340. fetched, it places the data in register 0 and requests service. It continues to
  1341. request service until the system retrieves its data.  The system responds to data-input
  1342. requests with the following polling sequence:
  1343.  
  1344.   •  It generates a Talk command for register 0 in each device connected
  1345.      to the ADB.
  1346.   •  If the device has data to send, it responds.  The system does not
  1347.      poll the next device until the data is exhausted.
  1348.   •  If the device has no data to send, or if its data is exhausted, the
  1349.      VIA generates an interrupt.  The system then polls the next device.
  1350.   •  This process continues until no devices request service.
  1351.  
  1352. »Register 3
  1353.  
  1354. Device register 3 is reserved for device identification data and operating flags.
  1355. Application programs may set this data with Listen commands and read it with Talk
  1356. commands. Register 3 stores 16 bits, divided into the fields shown in Figure 2.
  1357.  
  1358. •••Refer to Figure 2.•••
  1359.  
  1360. Figure 2–Format of Device Register 3
  1361.  
  1362. Except for commands that contain certain reserved device handler ID values
  1363. (listed below), every command to register 3 changes the entire register contents.
  1364. Hence to change part of the register, you should first fetch its current contents
  1365. with a Talk command and then send it an updated value with Listen. You can change
  1366. part of the contents of register 3 by using special device handler ID values, as
  1367. described below.
  1368.  
  1369. The device handler ID field indicates the device’s type. With certain devices, an
  1370. application can change the device’s mode of operation by sending it a new ID value.
  1371. If the device supports the new mode, it stores the new value in this field.
  1372.  
  1373. Warning:  You are assigned handler IDs by Apple Software Licensing, so
  1374.           they do not conflict with the values of other devices that may
  1375.           be connected to the ADB at the same time.
  1376.  
  1377. When certain reserved values are sent to the device handler ID field by a Listen
  1378. command, they are not stored in the field; instead, they cause specific device actions.
  1379. Hence these values cannot be used as device ID values. They are the following:
  1380.  
  1381.   Value  Action
  1382.  
  1383.   $00    Change bits 8–13 of register 3 to match the rest of the command;
  1384.          leave Device Handler ID value unchanged.
  1385.   $FD    Change Device Address to match bits 8–11 if the device activator
  1386.          has been depressed; leave Device Handler ID value and flags unchanged.
  1387.   $FE    Change Device Address to match bits 8–11 if the result produces no
  1388.          address duplication on the bus; leave Device Handler ID value and
  1389.          flags unchanged.
  1390.   $FF    Initiate device self-test. If self-test succeeds, leave register 3
  1391.          unchanged; if self-test fails, clear Device Handler ID field to $00.
  1392.  
  1393. Other Device Handler ID values may be stored in the field.
  1394.  
  1395. Note:  Device Handler ID values below $20 are reserved by Apple.
  1396.  
  1397. The Device Address field indicates the device’s location within the 16 possible
  1398. device locations of the ADB. An application may change its value with a Listen command.
  1399. When this field is interrogated with a Talk command, it returns a random value. This
  1400. helps you separate multiple devices that have the same ADB address; for further
  1401. information, see “Device Addressing”, below.
  1402.  
  1403. The Service Request Enable bit is set by the device to request an interrupt poll.
  1404.  
  1405. _______________________________________________________________________________
  1406.  
  1407. »Device Addressing
  1408.  
  1409. There are 16 possible direct addresses, $00–$0F, for devices connected to the ADB.
  1410. However, it is possible to connect more than one device to an address; this might
  1411. happen, for example, in a system with two alternate keyboards.
  1412.  
  1413. When several devices share a single ADB address, but there are free addresses available
  1414. in the net, the system will automatically reassign addresses until they are all
  1415. different. It will do this every time the ADB Manager is initialized or reinitialized.
  1416. To find out a device’s new address, use the calls GetIndADB or GetADBInfo, described
  1417. later in this chapter.
  1418.  
  1419. _______________________________________________________________________________
  1420.  
  1421. »Standard ADB Device Drivers
  1422.  
  1423. The Macintosh II and Macintosh SE systems contain two standard ADB drivers:
  1424.  
  1425.   •  the mouse driver, which supports the ADB mouse. The Apple mouse
  1426.      has an original ADB address of 3.
  1427.   •  the universal keyboard driver, which supports all Apple ADB keyboards.
  1428.      The Apple keyboard has an original ADB address of 2, with a Device
  1429.      Handler ID of 1 for the Macintosh II keyboard and 2 for the Apple
  1430.      Extended Keyboard.  These keyboards are described in the Toolbox
  1431.      Event Manager chapter. 
  1432.  
  1433. These drivers reside in the system ROM. In addition, ADB address 0 is reserved for
  1434. the ADB chip itself.  You can change the ADB addresses of the mouse or keyboard, as
  1435. described above under “Device Registers,” but Apple does not recommend doing so.
  1436.  
  1437. Assembly-language note:  The ADB address of the keyboard on which the
  1438.                          last-typed character was entered is now stored
  1439.                          in the global variable KbdLast. The type of the
  1440.                          keyboard on which the last-typed character was
  1441.                          entered is stored in the global variable KbdType.
  1442.                          The value of KbdType is the Device Handler ID
  1443.                          value in Register 3 of the device; values below
  1444.                          $20 are reserved by Apple.
  1445.  
  1446. The requirements for writing new ADB device drivers are discussed later in this
  1447. chapter.
  1448.  
  1449. _______________________________________________________________________________
  1450.  
  1451.  
  1452. æKY ADB…Manager…Routines
  1453. æC »ADB MANAGER ROUTINES                                      AppleDesktopBus
  1454. _______________________________________________________________________________
  1455.  
  1456. The ADB Manager consists of six routines located in the 256K ROM. You would use them
  1457. only if you needed to access bus devices directly or communicate with a special
  1458. device.
  1459.  
  1460. Some of these routines access and update information in the ADB device table, a
  1461. structure placed in the system heap by ROM code during system  startup. It lists for
  1462. each device the device’s type, its original ADB address, its current ADB address, the
  1463. address of the routine that services the device, and the address of the area in RAM
  1464. used for temporary data storage by its driver. The ADB device table is accessible
  1465. only through ADB Manager routines.
  1466.  
  1467. PROCEDURE ADBReInit;
  1468.  
  1469. Trap macro    _ADBReInit
  1470.  
  1471. ADBReInit reinitializes the entire Apple Desktop Bus. It clears the ADB device table
  1472. to zeros and places a SendReset command on the bus to reset all devices to their
  1473. original addresses. ADBReInit has no parameters.
  1474.  
  1475. Because it does not deallocate ADB resources on the system heap, ADBReInit should not
  1476. be used for routine bus initialization. Apple strongly recommends against adding
  1477. devices while the system is running; therefore, you should never call ADBReInit.
  1478.  
  1479. ADBReInit also calls a routine pointed to by the low memory global JADBProc
  1480. at the beginning and end of its execution.  You can insert your own
  1481. preprocessing/postprocessing routine by changing the value of JADBProc; ADBReInit
  1482. conditions it by setting D0 to 0 for preprocessing and to 1 for postprocessing.  Your
  1483. procedure must restore the value of D0 and branch to the original value of JADBProc
  1484. on exit.  JADBProc should be used to de-allocate memory used by the driver (see
  1485. MacDTS Sample Code “TbltDrvr” for an example), and then it should chain to the procedure
  1486. originally found in JADBProc.
  1487.  
  1488. The complete ADBReInit sequence is therefore the following:
  1489.  
  1490.   •  JSR to JADBProc with D0 set to 0
  1491.   •  reinitialize the Apple Desktop Bus
  1492.   •  clear the ADB device table
  1493.   •  JSR to JADBProc with D0 set to 1
  1494.  
  1495. FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
  1496.                 commandNum: INTEGER) : OSErr;
  1497.  
  1498. Trap macro    _ADBOp
  1499.  
  1500. On entry:    A0:  pointer to parameter block
  1501.              D0:  commandNum (byte)
  1502.  
  1503. Parameter block
  1504.     -->    0    buffer      pointer
  1505.     -->    4    compRout    pointer
  1506.     -->    8    data        pointer
  1507.  
  1508. On exit:     D0:  result code (byte)
  1509.  
  1510. The completion routine pointed to by compRout will be passed the following parameters
  1511. on entry:
  1512.  
  1513.              D0:  commandNum (byte)
  1514.              A0:  pointer to buffer, data stored as a Pascal string (maximum
  1515.                   8 bytes data preceded by one length byte)
  1516.              A1:  pointer to completion routine (compRout)
  1517.              A2:  pointer to optional data area (data)
  1518.  
  1519. ADBOp transmits over the bus the command byte whose value is given by commandNum. The
  1520. structure of the command byte is given earlier in Figure 1. ADBOp executes only when
  1521. the ADB is otherwise idle; otherwise it is held in a command queue. It returns an
  1522. error if the command queue is full. The length of the data buffer pointed to by
  1523. buffer is contained in its first byte, like a Pascal string. The optional data area
  1524. pointed to by data is for local storage by the completion routine pointed to by
  1525. compRout. ADBop should be used sparingly; it is not intended for polling a device. 
  1526. The host automatically polls devices with data to deliver.
  1527.  
  1528. Result codes    noErr    No error
  1529.                 –1       Unsuccessful completion
  1530.  
  1531. FUNCTION CountADBs: INTEGER;
  1532.  
  1533. Trap macro    _CountADBs
  1534.  
  1535. On exit:    D0:  number of devices (byte)
  1536.  
  1537. CountADBs returns a value representing the number of devices connected to the ADB by
  1538. counting the number of entries in the device table. It has no arguments and returns
  1539. no error codes.
  1540.  
  1541. FUNCTION GetIndADB (VAR info: ADBDataBlock;
  1542.                     devTableIndex: INTEGER) : ADBAddress;
  1543.  
  1544. Trap macro    _GetIndADB
  1545.  
  1546. On entry:    A0:  pointer to parameter block
  1547.              D0:  entry index number; range = 1..CountADBs (byte)
  1548.  
  1549. Parameter block
  1550.     <--    0    device type                byte    (handler ID)
  1551.     <--    1    original ADB address       byte
  1552.     <--    2    service routine address    pointer (compRout)
  1553.     <--    6    data area address          pointer (data)
  1554.  
  1555. On exit:     D0:  positive value:  current ADB address (byte)
  1556.                   negative value:  error code (byte)
  1557.  
  1558. GetIndADB returns information from the ADB device table entry whose index number is
  1559. given by devTableIndex. ADBDataBlock has this form:
  1560.  
  1561. TYPE  ADBDataBlock =
  1562.              PACKED RECORD
  1563.                devType:         SignedByte; {device type (handler ID)}
  1564.                origADBAddr:     SignedByte; {original ADB address}
  1565.                dbServiceRtPtr:  Ptr;        {service routine address (compRout)}
  1566.                dbDataAreaAddr:  Ptr         {data area address (data)}
  1567.              END;
  1568.  
  1569. GetIndADB returns the current ADB address of the device. If it is unable to complete
  1570. execution successfully, GetIndADB returns a negative value.
  1571.  
  1572. FUNCTION GetADBInfo (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
  1573.  
  1574. Trap macro    _GetADBInfo
  1575.  
  1576. On entry:    A0:  pointer to parameter block
  1577.              D0:  ADB address of the device (byte)
  1578.  
  1579. Parameter block
  1580.     <--    0    device handler ID          byte
  1581.     <--    1    original ADB address       byte
  1582.     <--    2    service routine address    pointer (compRout)
  1583.     <--    6    data area address          pointer (data)
  1584.  
  1585. On exit:     D0:  result code (byte)
  1586.  
  1587. GetADBInfo returns information from the ADB device table entry of the device whose
  1588. ADB address is given by ABDAddr. The structure of ADBDataBlock is given above under
  1589. “GetIndADB”.
  1590.  
  1591. Result codes    noErr    No error
  1592.  
  1593. FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
  1594.  
  1595. Trap macro    _SetADBInfo
  1596.  
  1597. On entry:    A0:  pointer to parameter block
  1598.              D0:  ADB address of the device (byte)
  1599.  
  1600. Parameter block
  1601.     -->    0    service routine address    pointer (compRout)
  1602.     -->    4    data area address          pointer (data)
  1603.  
  1604. On exit:     D0:  result code (byte)
  1605.  
  1606. SetADBInfo sets the service routine address and the data area address in the ADB
  1607. device table entry for the device whose ADB address is given by ABDAddr. ADBSetInfoBlock
  1608. has this form:
  1609.  
  1610. TYPE  ADBSetInfoBlock =
  1611.                RECORD
  1612.                  siServiceRtPtr:  Ptr;  {service routine address (compRout)}
  1613.                  siDataAreaAddr:  Ptr   {data area address (data)}
  1614.                END;
  1615.  
  1616. Result codes    noErr    No error
  1617.  
  1618. Warning:  You should send a Flush command to the device after calling it
  1619.           with SetADBInfo, to prevent it sending old data to the new data
  1620.           area address.
  1621.  
  1622. _______________________________________________________________________________
  1623.  
  1624.  
  1625. æKY Writing…ADB…Device…Drivers
  1626. æC »WRITING ADB DEVICE DRIVERS                                AppleDesktopBus
  1627. _______________________________________________________________________________
  1628.  
  1629. Drivers for devices connected to the ADB have the following special requirements:
  1630.  
  1631.   •  Each ADB device driver must reside in a resource of type 'ADBS'.
  1632.      (An example 'ADBS' resource is available in MacDTS Sample Code
  1633.      “TbltDrvr.”) This type has two sections: initialization and driver code.
  1634.   •  The initialization section of each ADB device driver must support the
  1635.      installation procedure described below.
  1636.  
  1637. When the system calls an ADB device driver, it passes it the following values:
  1638.  
  1639.   •  Register A0 points to the data buffer, which is formatted as a
  1640.      Pascal string (buffer).
  1641.   •  Register A1 points to the driver’s completion routine (compRout).
  1642.   •  Register A2 points to the optional data area (data).
  1643.   •  Register D0 contains the ADB command that resulted in the driver
  1644.      being called (commandNum).
  1645.  
  1646. The ADB driver should handle the ADB command passed to it and store any resulting
  1647. input data by an appropriate action, such as by posting an event or moving the cursor.
  1648.  
  1649. Note:  Events posted from keyboards connected to the ADB now have an
  1650.        expanded structure. For more information, see the Toolbox Event
  1651.        Manager chapter.
  1652.  
  1653. _______________________________________________________________________________
  1654.  
  1655. »Installing an ADB Driver
  1656.  
  1657. The Start Manager (described in this volume) finds all the ADB devices connected to
  1658. the system and places their device types and ADB addresses in the ADB device table.
  1659. It then calls the initialization section of each ADB device driver by executing the
  1660. initialization code in its 'ADBS' resource.
  1661.  
  1662. As a minimum, the initialization section of each ADB device driver must do the following:
  1663.  
  1664.   •  The driver must allocate all the memory required by the driver code
  1665.      in one or more nonrelocatable blocks in the system heap area.
  1666.   •  The driver must install its own preprocessing/postprocessing routine
  1667.      (if any) as described above under “ADBReInit”.
  1668.   •  Finally, the driver must initialize the service routine address and
  1669.      data area address of its entry in the ADB device table, using SetADBInfo.
  1670.  
  1671. _______________________________________________________________________________
  1672.  
  1673.  
  1674. æKY Summary…of…the…ADB
  1675. æC »SUMMARY OF THE ADB MANAGER                                AppleDesktopBus
  1676. _______________________________________________________________________________
  1677.  
  1678. Data Types
  1679.  
  1680. TYPE
  1681.   ADBDataBlock =
  1682.          PACKED RECORD
  1683.            devType:         SignedByte;  {Handler ID}
  1684.            origADBAddr:     SignedByte;  {original ADB address}
  1685.            dbServiceRtPtr:  Ptr;         {service routine address (compRout)}
  1686.            dbDataAreaAddr:  Ptr          {data area address (area)}
  1687.          END;
  1688.  
  1689.   ADBSetInfoBlock =
  1690.            RECORD
  1691.              siServiceRtPtr:  Ptr;  {service routine address}
  1692.              siDataAreaAddr:  Ptr   {data area address}
  1693.            END;
  1694.  
  1695. _______________________________________________________________________________
  1696.  
  1697. Routines
  1698.  
  1699. Initializing the ADB Manager
  1700.  
  1701. PROCEDURE ADBReInit;
  1702.  
  1703. Communicating Through the ADB
  1704.  
  1705. FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
  1706.                 commandNum: INTEGER) : OSErr;
  1707.  
  1708. Getting ADB Device Information
  1709.  
  1710. FUNCTION CountADBs:  INTEGER;
  1711. FUNCTION GetIndADB   (VAR info: ADBDataBlock;
  1712.                       devTableIndex: INTEGER) : ADBAddress;
  1713. FUNCTION GetADBInfo  (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
  1714.  
  1715. Setting ADB Device Information
  1716.  
  1717. FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
  1718.  
  1719. _______________________________________________________________________________
  1720.  
  1721. Assembly-Language Information
  1722.  
  1723. Variables
  1724.  
  1725. JADBProc    Pointer to ADBReInit preprocessing/postprocessing routine
  1726. KbdLast     ADB address of the keyboard last used (byte)
  1727. KbdType     Keyboard type of the keyboard last used (byte)
  1728.  
  1729. Routines
  1730.  
  1731. Trap macro     On entry                               On Exit
  1732.  
  1733. _ADBReInit
  1734.  
  1735. _ADBOp         A0:  pointer to parameter block        D0:  result code (byte)
  1736.                     buffer (pointer)
  1737.                     compRout (pointer)
  1738.                     data (pointer)
  1739.                D0:  commandNum (byte)
  1740.  
  1741. _CountADBs                                            D0:  result code (byte)
  1742.  
  1743. _GetIndADB     A0:  pointer to parameter block        D0:  positive value:
  1744.                     device type (byte)                       current ADB
  1745.                     original ADB address (byte)              address (byte)
  1746.                     service routine address (pointer)        negative value:
  1747.                     data area address (pointer)              error code (byte)
  1748.                D0:  entry index number;
  1749.                     range = 1..CountADBs (byte)
  1750.  
  1751. _GetADBInfo    A0:  pointer to parameter block        D0:  result code (byte)
  1752.                     device handler ID (byte)           
  1753.                     original ADB address (byte)   
  1754.                     service routine address (pointer)   
  1755.                     data area address (pointer)
  1756.                D0:  current ADB address of the device (byte)
  1757.  
  1758. _SetADBInfo    A0:  pointer to parameter block        D0:  result code (byte)
  1759.                     service routine address (pointer)   
  1760.                     data area address (pointer)
  1761.                D0:  current ADB address of the device (byte)
  1762.  
  1763. Further Reference:
  1764. _______________________________________________________________________________
  1765. Toolbox Event Manager
  1766. Technical Note #143, Don’t Call ADBReInit on the SE with System 4.1
  1767. Technical Note #160, Key Mapping
  1768. Technical Note #206, Space Aliens Ate My Mouse
  1769. “Macintosh Family Hardware Reference”
  1770.  
  1771.  
  1772. æKY AppleTalkManager
  1773. æC 
  1774. _______________________________________________________________________________
  1775.  
  1776. APPLETALK MANAGER
  1777. _______________________________________________________________________________
  1778.  
  1779. About…the…AppleTalk…Manager…Vol…VI…Chapter
  1780. About…the…AppleTalk…Manager…Vol…VI
  1781.     Changes…to…the…AppleTalk…Manager…Vol…VI
  1782.     AppleTalk…Protocols…Vol…VI
  1783.     AppleTalk…Device…Drivers,…'adev'…Files,…and…the…LAP…Manager
  1784. Using…the…AppleTalk…Manager…Vol…VI
  1785.     Determining…Whether…AppleTalk…Phase…2…Drivers…Are…Present
  1786.     Determining…Which…AppleTalk…Protocol…to…Use
  1787. The….MPP…Driver
  1788.     Getting…Information…About…the….MPP…Driver
  1789.     A…New…NBP…Wildcard…Character
  1790. The…LAP…Manager
  1791.     The…AppleTalk…Transition…Queue
  1792.     Adding…and…Removing…AppleTalk…Transition…Queue…Entries
  1793.     Sending…Messages…to…the…AppleTalk…Transition…Queue
  1794.     How…the…AppleTalk…Manager…Calls…Your…Transition…Queue…Routine
  1795.     The…LAP…Manager…802.2…Protocol
  1796.     Attaching…and…Detaching…802.2…Protocol…Handlers
  1797. AppleTalk…Data…Stream…Protocol…(ADSP)
  1798.     Using…ADSP
  1799.     The…ADSP…Connection…Control…Block
  1800.     The….DSP…Parameter…Block
  1801.     Opening…and…Maintaining…an…ADSP…Connection
  1802.     Creating…and…Using…a…Connection…Listener
  1803.     Writing…a…User…Routine…For…Connection…Events
  1804.     DSP…Driver…Commands
  1805.     Establishing…and…Terminating…an…ADSP…Connection
  1806.     Establishing…and…Terminating…an…ADSP…Connection…Listener
  1807.     Maintaining…an…ADSP…Connection
  1808. The….ATP…Driver
  1809.     Canceling…All…Calls…to…the…ATPGetRequest…Function
  1810.     Setting…the…Timeout…Value…For…the…ATP…Release…Timer
  1811. The….XPP…Driver
  1812.     Using…the….XPP…Driver…to…Obtain…Zone…Information
  1813.     XPP…Driver…Routines
  1814. The….ENET…Driver
  1815.     Changing…the…Ethernet…Hardware…Address
  1816.     Opening…the….ENET…Driver
  1817.     Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
  1818.     Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
  1819.     Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
  1820.     How…the….ENET…Driver…Calls…Your…Protocol…Handler
  1821.     How…Your…Protocol…Handler…Calls…the….ENET…Driver
  1822.     ENET…Driver…Routines
  1823.     Attaching…and…Detaching…an…Ethernet…Protocol…Handler
  1824.     Writing…and…Reading…Packets…Using…the…Default…Protocol…Handler
  1825.     Adding…and…Removing…Ethernet…Multicast…Addresses
  1826. Summary…of…the…AppleTalk…Manager…Vol…VI
  1827.     AppleTalk…Constants
  1828.     AppleTalk…Data…Types
  1829.     AppleTalk…Routines
  1830.     AppleTalk…Result…codes
  1831.     Assembly-language…Information…for…AppleTalk
  1832.  
  1833. About…The…AppleTalkManager…Chapter
  1834. AppleTalk…Protocols
  1835. AppleTalk…Transaction…Protocol
  1836. About…the…AppleTalk…Manager
  1837. Calling…the…AppleTalk…Manager…from…Pascal
  1838. New…AppleTalk…Manager…Pascal…Interface
  1839. Picking…a…Node…Address…in…the…Server…Range
  1840. Sending…Packets…to…One’s…Own…Node
  1841. ATP…Driver…Changes
  1842. Name…Binding…Protocol…Changes
  1843. Variable…Resources
  1844. Calling…the…AppleTalk…Manager…from…Assembly…Language
  1845. Extended…Protocol…Package…Driver
  1846. Calling…the….XPP…Driver
  1847. Protocol…Handlers…and…Socket…Listeners
  1848. Summary…of…the…AppleTalk…Manager
  1849. _______________________________________________________________________________
  1850.  
  1851.  
  1852. æKY About…the…AppleTalk…Manager…Vol…VI…Chapter
  1853. æC »ABOUT THIS CHAPTER                                                   AppleTalk Manager
  1854. _______________________________________________________________________________
  1855.  
  1856. AppleTalk is a communication network system including personal computer
  1857. workstations, computers acting as file servers and print servers, printers, and
  1858. a variety of types of communication hardware and software. The AppleTalk Manager
  1859. provides an interface to this communication network system for applications
  1860. running on Macintosh computers. This chapter describes the changes to the
  1861. AppleTalk Manager introduced as AppleTalk Phase 2 and included with system
  1862. software version 7.0. This chapter supplements the information in the AppleTalk
  1863. Manager chapters of Inside Macintosh, Volumes II and V.
  1864.  
  1865. This chapter describes 
  1866.   •   new routines for the .MPP, .ATP, and .XPP device drivers
  1867.  
  1868.   •   a new wildcard character for use with the Name-Binding Protocol
  1869.  
  1870.   •   a new system queue, called the AppleTalk Transition Queue
  1871.  
  1872.   •   a new set of operating system utilities, collectively called the LAP
  1873.       Manager.
  1874.  
  1875.   •   the .ENET driver and the routines your application can use to control
  1876.       this driver
  1877.  
  1878.   •   the application interface routines provided by a new AppleTalk protocol,
  1879.       the AppleTalk Data Stream Protocol
  1880.  
  1881. Together with the AppleTalk Manager chapters of Volumes II and V, this chapter
  1882. describes the routines that your application can use to send and receive
  1883. information within an AppleTalk network system . Because the AppleTalk network
  1884. system includes both hardware and software, and because the software includes
  1885. not only the AppleTalk Manager but file servers, print servers, internet
  1886. routers, drivers for circuit cards, and so forth, the information in Inside
  1887. Macintosh constitutes only a small part of the body of literature documenting
  1888. AppleTalk.
  1889.  
  1890. For a detailed description of AppleTalk protocols, see Inside AppleTalk. For a
  1891. complete description of the LAP Manager, EtherTalk, and alternate AppleTalk
  1892. connections, see the AppleTalk Connections Programmer’s Guide. To learn how to
  1893. install and operate an AppleTalk internet, see the AppleTalk Internet Router
  1894. Administrator’s Guide and the AppleTalk Phase 2 Introduction and Upgrade Guide.
  1895. For an introduction to the hardware and software of an entire AppleTalk network,
  1896. see Understanding Computer Networks and the AppleTalk Network System Overview.
  1897. For information on designing circuit cards and device drivers for Macintosh
  1898. computers, see Designing Cards and Drivers for the Macintosh Family.
  1899.  
  1900. You can install the Phase 2 versions of the AppleTalk drivers on any Macintosh
  1901. computer other than the Macintosh XL, Macintosh 128K, Macintosh 512K, and
  1902. Macintosh 512K enhanced computers. If you want to provide AppleTalk Phase 2
  1903. device drivers with your product, you must obtain a license from Apple Software
  1904. Licensing.
  1905.  
  1906. _______________________________________________________________________________
  1907.  
  1908. æKY About…the…AppleTalk…Manager…Vol…VI
  1909. æC »ABOUT THE APPLETALK MANAGER                                          AppleTalk Manager
  1910. _______________________________________________________________________________
  1911.  
  1912. The AppleTalk Manager includes a number of protocols that are implemented in
  1913. various device drivers. The AppleTalk Manager also includes the LAP Manager,
  1914. which interfaces the AppleTalk data links to the AppleTalk protocols; and
  1915. hardware device drivers for specific networks. The AppleTalk data links are
  1916. contained in files of type 'adev', sometimes referred to as 'adev' files. This
  1917. section lists the new features that have been introduced as AppleTalk Phase 2,
  1918. describes the organization of the AppleTalk Manager, and briefly discusses what
  1919. each component of the AppleTalk Manager does.
  1920.  
  1921.  
  1922. _______________________________________________________________________________
  1923.  
  1924. æKY Changes…to…the…AppleTalk…Manager…Vol…VI
  1925. æC »Changes to the AppleTalk Manager                                     AppleTalk Manager
  1926. _______________________________________________________________________________
  1927.  
  1928. The features that have been introduced as AppleTalk Phase 2 include
  1929.  
  1930.   •   a new .MPP driver function that returns information about the .MPP driver
  1931.  
  1932.   •   a new protocol, the AppleTalk Data Stream Protocol (ADSP), which provides
  1933.       full-duplex data stream communications for use by applications; see
  1934.       “AppleTalk Data Stream Protocol”
  1935.  
  1936.   •   improvements to the Zone Information Protocol (ZIP) that allow a single
  1937.       network (other than LocalTalk) to contain more than one zone; see
  1938.       “Obtaining Zone Information.”
  1939.  
  1940.   •   new functions for the .XPP device driver that provide information from
  1941.       ZIP about zones; see “The .XPP Driver”
  1942.  
  1943.   •   a new Name Binding Protocol (NBP) wildcard character that can substitute
  1944.       for one or more characters in AppleTalk names; see “A New NBP Wildcard
  1945.       Character”
  1946.  
  1947.   •   the AppleTalk Transition Queue, an operating system queue that can notify
  1948.       your application each time an AppleTalk driver is opened or closed, or
  1949.       certain other transitions occur; see “The AppleTalk Transition Queue”
  1950.  
  1951.   •   the LAP Manager, a new set of operating system utilities that provide a
  1952.       standard interface between the AppleTalk protocols and the data links
  1953.       used by Appletalk, such as EtherTalk, LocalTalk, and TokenTalk; see “The
  1954.       LAP Manager”
  1955.  
  1956.   •   the .ENET driver, an Ethernet driver for the EtherTalk NuBus card that is
  1957.       manufactured by Apple Computer, Inc.; see “The .ENET Driver”
  1958.  
  1959.   •   an implementation of the IEEE 802.2 protocol, which allows you to attach
  1960.       and detach your own protocol handlers for EtherTalk and TokenTalk data
  1961.       packets; see “The LAP Manager 802.2 Protocol”
  1962.  
  1963.   •   new .ATP driver functions that allow you to set a value for the .ATP
  1964.       release timer and to cancel all pending asynchronous calls to the
  1965.       ATPGetRequest function for a specific socket; see “The .ATP Driver”
  1966. _______________________________________________________________________________
  1967.  
  1968. æKY AppleTalk…Protocols…Vol…VI
  1969. æC »AppleTalk Protocols                                                  AppleTalk Manager
  1970. _______________________________________________________________________________
  1971.  
  1972. The AppleTalk Manager comprises the following protocols:
  1973.  
  1974.   •   LocalTalk Link Access Protocol (LLAP)
  1975.   •   Datagram Delivery Protocol (DDP)
  1976.   •   Routing Table Maintenance Protocol (RTMP)
  1977.   •   AppleTalk Transaction Protocol (ATP)
  1978.   •   Name-Binding Protocol (NBP)
  1979.   •   AppleTalk Echo Protocol (AEP)
  1980.   •   Zone Information Protocol (ZIP)
  1981.   •   AppleTalk Session Protocol (ASP)
  1982.   •   AppleTalk Data Stream Protocol (ADSP)
  1983.   •   AppleTalk Filing Protocol (AFP)
  1984.  
  1985. The EtherTalk Link Access Protocol, TokenTalk Link Access Protocol, and other
  1986. Link Access Protocols provide interfaces between the AppleTalk Manager and the
  1987. different types of data link hardware used by AppleTalk.
  1988.  
  1989. Note:  The LocalTalk Link Access Protocol (LLAP) was originally called the
  1990. AppleTalk Link Access Protocol (ALAP). It has been renamed to avoid confusion
  1991. with the EtherTalk Link Access Protocol and other link access protocols.
  1992.  
  1993. Figure 29-1 shows the relationships among the various AppleTalk protocols. A
  1994. line going from a protocol to another protocol above or below it in the figure
  1995. indicates that the upper protocol is a client of the lower protocol; that is,
  1996. the upper protocol uses services provided by the lower protocol in order to
  1997. carry out some functions.
  1998.  
  1999. Note:  The various AppleTalk protocols are sets of rules, not computer programs,
  2000. and so can be implemented in many different ways on many different systems. All
  2001. of the AppleTalk protocol functions that you can address or control from a
  2002. Macintosh application are implemented as Macintosh device drivers or managers.
  2003. Many other features of these protocols are implemented in software located only
  2004. on internet routers that are not used to run general applications. Some parts of
  2005. protocols are implemented by server software such as file servers and print
  2006. servers. Therefore, when this chapter refers to a protocol as “doing” or 
  2007. “controlling” something, you should understand the statement to mean that some
  2008. program that implements the protocol actually carries out the operation.
  2009.  
  2010. ø 29.1  AppleTalk Protocols
  2011.  
  2012. A link access protocol controls the access of the node to the network hardware,
  2013. making it possible for many nodes to share the same communication hardware. Each
  2014. link access protocol assigns a node ID to the node and decodes the node
  2015. addresses of messages it receives. A link access protocol provides node-to-node
  2016. delivery of data packets. Examples of link access protocols include the
  2017. LocalTalk Link Access Protocol, the EtherTalk Link Access Protocol, and the
  2018. TokenTalk Link Access Protocol.
  2019.  
  2020. Whereas earlier implementations of AppleTalk were restricted to one 16-bit
  2021. network number per cable (that is, one network number for all nodes connected
  2022. with no intervening routers) and 254 nodes per network number, AppleTalk Phase 2
  2023. allows more than one network number for each cable (other than LocalTalk, which
  2024. is still limited to one network number on a cable). Each node in a network other
  2025. than LocalTalk must be specified by both its 16-bit network number and its 8-bit
  2026. node ID. In principle, each cable (other than LocalTalk) can now have over 16
  2027. million (224) nodes. In any specific implementation, the hardware or software
  2028. might limit the network to fewer nodes.
  2029.  
  2030. Note:  Before the introduction of AppleTalk Phase 2, AppleTalk allowed only one
  2031. network number per cable (that is, one network number for all nodes connected
  2032. with no intervening routers), and the term network was used to include all of
  2033. the nodes connected by a single cable. Under AppleTalk Phase 2, however, more
  2034. than one network number can be assigned to a single cable. The term network is
  2035. now sometimes used to refer to the collection of all the nodes that share a
  2036. single network number, and is sometimes used in the older sense to refer to all
  2037. nodes connected with no intervening routers. In the latter case, you could say
  2038. that a single network can have a range of network numbers. Because of this
  2039. ambiguity, it is best to avoid using the term network without modifiers. 
  2040.  
  2041. The Datagram Delivery Protocol provides socket-to-socket delivery of data
  2042. packets within an AppleTalk internet. A DDP packet’s address includes the socket
  2043. number, node ID, and network number. Application-interface routines for DDP are
  2044. described in “Datagram Delivery Protocol” in the AppleTalk Manager chapter of
  2045. Volume II.
  2046.  
  2047. The Routing Table Maintenance Protocol is used by routers on an AppleTalk
  2048. internet to determine how to forward a data packet to the network number to
  2049. which it is addressed. The RTMP implementation on a router maintains a table,
  2050. called a routing table, that specifies the shortest path to each possible
  2051. destination network number. The AppleTalk protocol software in a workstation
  2052. contains only a small part of RTMP, called the RTMP stub, that DDP uses to
  2053. determine the network number (or range of network numbers) of the network cable
  2054. to which the node is connected and the network number and node ID of one router
  2055. on that network cable. There is no application interface to the RTMP stub.
  2056.  
  2057. The AppleTalk Transaction Protocol provides loss-free communications by
  2058. retransmitting any data packets that are lost. Although—as you can see from
  2059. Figure 29-1—the AppleTalk Manager provides high-level protocols that are clients
  2060. of ATP, many applications use ATP directly to transmit data over an AppleTalk
  2061. internet. The application interface to ATP is described in the AppleTalk Manager
  2062. chapter of Volume II. There are some enhancements to ATP in AppleTalk Phase 2,
  2063. described in “Changes to the .ATP Driver” later in this chapter.
  2064.  
  2065. The Name-Binding Protocol maintains a table that contains the internet address
  2066. and name of each entity in the node that is visible to other entities on the
  2067. internet. The internet address includes the socket number, node ID, and network
  2068. number. The name consists of three fields: the object, type, and zone. The
  2069. object and type are assigned by the entity itself and can be anything the user
  2070. or application assigns. A zone is a logical grouping of a subset of the nodes on
  2071. the internet. The zone field of the name is the zone in which the node resides.
  2072.  
  2073. NBP also allows its clients to obtain the internet address of any
  2074. network-visible entity in the internet by providing its name. NBP maps this name
  2075. to an internet address, thus providing the link between the user-supplied name
  2076. for an entity and the internet address that is used by DDP to send and receive
  2077. data packets. The application interface to NBP is described in the AppleTalk
  2078. Manager chapter of Volume II. There is one enhancement to NBP in AppleTalk Phase
  2079. 2, described in “A New NBP Wildcard Character” later in this chapter.
  2080.  
  2081. The AppleTalk Echo Protocol listens for special packets sent by other nodes and,
  2082. when it receives such a packet, echoes it back to the sender. The AEP is used by
  2083. some clients of DDP to determine whether another node (known to have AEP) can be
  2084. accessed over the internet, and to determine how long it takes a packet to reach
  2085. another node. There is no application interface to AEP.
  2086.  
  2087. The Zone Information Protocol maintains a table in each router, called the zone
  2088. information table, that lists the relationships between zone names and networks.
  2089. In AppleTalk Phase 2, a network (other than LocalTalk) can contain more than one
  2090. zone or a zone can contain more than one network. You can use .XPP driver
  2091. routines to obtain information from ZIP; these routines are discussed in 
  2092. “Obtaining Zone Information” later in this chapter.
  2093.  
  2094. The AppleTalk Session Protocol sets up and maintains sessions between a
  2095. workstation and a server. A session consists of a logical (as opposed to
  2096. physical) connection between two entities on the internet. ASP is a
  2097. nonsymmetrical protocol; that is, only one of the two entities involved in the
  2098. session (the workstation) can send commands; the other entity (the server) is
  2099. restricted to responding to the commands. ASP is used by the AppleTalk Filing
  2100. Protocol, for example, to allow a user to manipulate files on a file server. As
  2101. long as the session is open, the workstation can request directory information,
  2102. change file names, and so forth. The file server must respond to the
  2103. workstation’s commands and cannot initiate any actions on its own. ASP is
  2104. discussed in the AppleTalk Manager chapter of Volume V.
  2105.  
  2106. The AppleTalk Data Stream Protocol appears to its clients to maintain an open
  2107. pipeline between two entities on the internet. Either entity can write a stream
  2108. of bytes to the pipeline, or read data bytes from the pipeline. ADSP is a
  2109. symmetrical protocol; that is, the two clients at either end of the connection
  2110. are equal and can perform exactly the same operations. ADSP is especially useful
  2111. for exchanging information between two equal entities, as in a telephone
  2112. communication network, or for sending or receiving a continuous stream of data,
  2113. as required by a terminal emulation program, for example. Because ADSP is a
  2114. client of DDP, the data is actually sent as data packets, allowing ADSP to
  2115. correct errors in transmission in a way that would not be possible for a true
  2116. data stream connection. Thus, ADSP retains many of the advantages of a
  2117. transaction-based protocol while providing to its clients a full-duplex data
  2118. stream. ADSP is discussed in the sections “Using ADSP” and “.DSP Driver
  2119. Functions” later in this chapter.
  2120.  
  2121. The AppleTalk Filing Protocol provides an interface between an application and a
  2122. file server. AFP is a client of ASP, and is used to access AppleShare file
  2123. servers on Macintosh computer workstations. When the user opens a session with
  2124. an AppleShare file server over an internet, it appears to any application
  2125. running on the workstation that uses File Manager routines as if the files on
  2126. the file server were located on a disk drive connected to the workstation. The
  2127. application interface to AFP is described in the AppleTalk Manager chapter of
  2128. Volume V. 
  2129. _______________________________________________________________________________
  2130.  
  2131. æKY AppleTalk…Device…Drivers,…'adev'…Files,…and…the…LAP…Manager
  2132. æC »AppleTalk Device Drivers, 'adev' Files, and the LAP Manager          AppleTalk Manager
  2133. _______________________________________________________________________________
  2134.  
  2135. A protocol is only a set of rules, not a computer program. The various AppleTalk
  2136. protocols are implemented as Macintosh device drivers, including
  2137.  
  2138.   •   the .MPP driver, which implements LLAP, DDP, NBP, AEP, and the RTMP stub
  2139.   •   the .ATP driver, which implements ATP
  2140.   •   the .XPP driver, which implements ASP and the workstation portions of ZIP
  2141.       and AFP
  2142.   •   the .DSP driver, which implements ADSP
  2143.   •   the .ENET driver, which implements Ethertalk
  2144.  
  2145. AppleTalk can also include one or more 'adev' files. An 'adev' file has file
  2146. type 'adev' and contains a link access protocol implementation for a network 
  2147. (ELAP for Ethernet, for example). The LAP Manager makes it possible for the user
  2148. to select among 'adev' files by using the Network control panel to control which
  2149. network is used for the node’s AppleTalk connection. The 'adev' file and LAP
  2150. Manager work together with the Network control panel (Network cdev) file. When
  2151. the user selects a connection from the Network control panel, the LAP Manager
  2152. routes AppleTalk communications through the selected link access protocol and
  2153. hence through the selected hardware.
  2154.  
  2155. The AppleTalk device drivers, LAP Manager, and 'adev' files are shown in Figure
  2156. As you can see from the figure, each device driver implements one or more
  2157. AppleTalk protocols.
  2158.  
  2159. ø 29.2  AppleTalk Device Drivers
  2160.  
  2161. Figure 29-3 shows the interfaces between a general application on a Macintosh
  2162. computer being used as an AppleTalk workstation and the AppleTalk protocols, the
  2163. LAP Manager, and the Ethernet hardware device driver. The lines connecting the
  2164. application to the various components of AppleTalk indicate which components
  2165. have application interfaces. As discussed in the preceding section, “AppleTalk
  2166. Protocols,” each application interface is described at least in part in this or
  2167. another volume of Inside Macintosh. 
  2168.  
  2169. ø 29.3  AppleTalk Application Interfaces.
  2170.  
  2171. _______________________________________________________________________________
  2172.  
  2173. æKY Using…the…AppleTalk…Manager…Vol…VI
  2174. æC »USING THE APPLETALK MANAGER                                          AppleTalk Manager
  2175. _______________________________________________________________________________
  2176.  
  2177. This section describes how to determine whether AppleTalk Phase 2 drivers are
  2178. present and gives some advice on how to select the AppleTalk protocol that best
  2179. servers your purposes. This section also describes how to use the features added
  2180. to AppleTalk with Phase 2 and provides programming examples of the use of the 
  2181. .DSP driver and several other new AppleTalk features.
  2182.  
  2183. _______________________________________________________________________________
  2184.  
  2185. æKY Determining…Whether…AppleTalk…Phase…2…Drivers…Are…Present
  2186. æC »Determining Whether AppleTalk Phase 2 Drivers Are Present            AppleTalk Manager
  2187. _______________________________________________________________________________
  2188.  
  2189. Once the .MPP driver has been loaded into memory, you can use the Gestalt
  2190. function to check the version of AppleTalk. The Gestalt function returns the
  2191. version of the .MPP driver; if the version is greater than or equal to 53, then
  2192. the .MPP driver supports AppleTalk Phase 2, and you can assume the other Phase 2
  2193. drivers are present as well.
  2194.  
  2195. Alternatively, you can call the SysEnvirons function as described in Chapter 1
  2196. of Volume V. If the atDrvrVersNum field of the SysEnvRec record returned by this
  2197. function is greater than or equal to 53, the .MPP driver supports AppleTalk
  2198. Phase 2.
  2199.  
  2200. _______________________________________________________________________________
  2201.  
  2202. æKY Determining…Which…AppleTalk…Protocol…to…Use
  2203. æC »Determining Which AppleTalk Protocol to Use                          AppleTalk Manager
  2204. _______________________________________________________________________________
  2205.  
  2206. AppleTalk offers a variety of communication protocols at a variety of levels.
  2207. Your choice of protocol or protocols to use depends primarily on your needs, and
  2208. can be influenced by your familiarity with network communications in general. 
  2209. You can write your own protocol handlers and call the low-level AppleTalk device
  2210. drivers directly. However, if you are not communications expert and have no
  2211. desire to design your own network protocols, you should probably use one of
  2212. three AppleTalk protocols for sending and receiving data over the AppleTalk
  2213. internet: the AppleTalk Transaction Protocol (ATP), the AppleTalk Session
  2214. Protocol (ASP), or the AppleTalk Data Stream Protocol (ADSP). 
  2215.  
  2216. ATP is a lower-level protocol than ASP or ADSP. You cannot use ATP to establish
  2217. a session and keep it open; rather, you request data from another socket or send
  2218. a response (up to eight packets of data) from your socket to another socket that
  2219. has requested data. You should use ATP if you want only to send a small amount
  2220. of data and do not need the overhead required to maintain an open connection.
  2221. ATP is described in the AppleTalk Manager chapters of Volume II and Volume V.
  2222.  
  2223. ASP is designed to support a session between a server and one or more
  2224. workstations. It is an asymmetrical protocol: all exchanges are initiated by a
  2225. workstation and responded to by a server. The server cannot initiate an exchange
  2226. of data except to send an attention message to a workstation, asking the
  2227. workstation to request data from the server. An application running on a
  2228. workstation must make calls to ASP to communicate with any server that uses ASP.
  2229. If you want to develop a new type of asymmetrical, transaction-oriented server,
  2230. you should consider using ASP to implement it. ASP is described in the AppleTalk
  2231. Manager chapter of Volume V.
  2232.  
  2233. ADSP is a symmetrical protocol that you can use to establish and maintain a
  2234. connection between two equal entities. Either end of an ADSP connection can send
  2235. data at any time. Although ADSP is a client of DDP, and therefore sends and
  2236. receives data in packets (as do ATP and ASP), to an application using ADSP the
  2237. data appears to be sent and received as a continuous stream. In addition to the
  2238. duplex data stream maintained by an ADSP session, ADSP allows either end of a
  2239. connection to send an attention message to the other end. You can use ADSP to
  2240. establish two-way communication between computers, such as an interoffice party
  2241. line or a terminal-emulation program. If you want to develop a server that
  2242. requires two-way communication, you should consider using ADSP to implement it.
  2243. ADSP is described in “Using ADSP” later in this chapter.
  2244.  
  2245. _______________________________________________________________________________
  2246.  
  2247. æKY The….MPP…Driver
  2248. æC »THE .MPP DRIVER                                                      AppleTalk Manager
  2249. _______________________________________________________________________________
  2250.  
  2251. Within the AppleTalk Manager, the .MPP driver implements the Routing Table
  2252. Maintenance Protocol (RTMP) stub, the Name Binding Protocol (NBP), the AppleTalk
  2253. Echo Protocol (AEP), the Datagram Delivery Protocol (DDP), and the LocalTalk
  2254. Link Access Protocol (LLAP). The AppleTalk Phase 2 version of the .MPP driver
  2255. includes a new function that returns information about the .MPP driver,
  2256. functions that send messages to routines in the AppleTalk Transition Queue, and
  2257. a new wildcard character for NBP.
  2258.  
  2259. _______________________________________________________________________________
  2260.  
  2261. æKY Getting…Information…About…the….MPP…Driver
  2262. æC »Getting Information About the .MPP Driver                            AppleTalk Manager
  2263. _______________________________________________________________________________
  2264.  
  2265. You can use the PGetAppleTalkInfo function to obtain information about the .MPP
  2266. driver. In addition to the node ID and other information pointed to by the
  2267. ABusVars global variable (discussed in the AppleTalk Manager chapter of Volume
  2268. II), the PGetAppleTalkInfo function returns 
  2269.  
  2270.   •   a pointer to the .MPP driver’s device control entry data structure (DCE)
  2271.  
  2272.   •   configuration flags, which indicate the status of certain conditions that
  2273.       are set at startup
  2274.  
  2275.   •   a value (the selfSend flag) that indicates whether the node can send
  2276.       packets to itself
  2277.  
  2278.   •   the network number range for the network to which the node is attached
  2279.  
  2280.   •   the 8-bit node ID and 16-bit network number of the node
  2281.  
  2282.   •   the 8-bit node ID and 16-bit network number of the last router from which
  2283.       the node has heard
  2284.  
  2285.   •   the maximum capacities of the .MPP driver—such as the maximum number of
  2286.       protocol handlers and the maximum number of static sockets allowed by
  2287.       this driver
  2288.  
  2289.   •   a pointer to the registered names queue
  2290.  
  2291.   •   the node address of the node on the underlying data link (for example,
  2292.       the Ethernet hardware address)
  2293.  
  2294.   •   the node’s zone name
  2295.  
  2296. The data link address (for example, the Ethernet hardware address) and the zone
  2297. name are returned only for extended networks; that is, network types that allow
  2298. more than one network per cable. You must allocate memory for and provide
  2299. pointers to the data buffers into which the PGetAppleTalkInfo function returns
  2300. the data link address and zone name. You use the laLength parameter to specify
  2301. the length of the data link address you want returned; the function returns the
  2302. actual length of the data in the laLength parameter and returns the data in the
  2303. buffer you provide.
  2304.  
  2305. Note:  Always use the PGetAppleTalkInfo function to obtain information about the
  2306. .MPP driver. You can no longer rely on the validity of the global variables
  2307. described in the AppleTalk chapter of Inside Macintosh, Volume II.
  2308.  
  2309. FUNCTION PGetAppleTalkInfo (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  2310.  
  2311. Parameter block
  2312.   ¨  16  ioResult  word  result code 
  2313.   Æ  26  csCode  word  always PGetAppleTalkInfo
  2314.   Æ  28  version  word  version of function
  2315.   ¨  30  varsPtr  pointer  pointer to MPP globals
  2316.   ¨  34  dcePtr  pointer  pointer to DCE for .MPP
  2317.   ¨  38  portID  word  port number 
  2318.   ¨  40  configuration  long  configuration flags
  2319.   ¨  44  selfSend  word  nonzero if self-send is enabled
  2320.   ¨  46  netLo  word  low value of the network range
  2321.   ¨  48  netHi  word  high value of the network range
  2322.   ¨  50  ourAddr  long  local 24-bit AppleTalk address
  2323.   ¨  54  routerAddr  long  24-bit address of router
  2324.   ¨  58  numOfPHs  word  max number of protocol handlers
  2325.   ¨  60  numOfSkts  word  max number of static sockets
  2326.   ¨  62  numNBPEs  word  max concurrent NBP requests
  2327.   ¨  64  ntQueue  pointer  pointer to registered name queue
  2328.   ´  68  laLength  word  length in bytes of data link address
  2329.           (extended networks only)
  2330.   Æ  70  linkAddr  pointer  pointer to data link address buffer
  2331.           (extended networks only)
  2332.   Æ  74  zoneName  pointer  pointer to zone name buffer
  2333.  
  2334. The PGetAppleTalkInfo function returns information about the .MPP driver. If the
  2335. node on which your program is running happens also to be running AppleTalk
  2336. Internet Router software in the background, there may be more than one set of 
  2337. .MPP global variables in RAM. To make sure you are obtaining information about
  2338. the .MPP driver that handles application software, always use the
  2339. PGetAppleTalkInfo function rather than the Device Manager’s PBControl function.
  2340. If you are using assembly language, or want to use the PBControl function, you
  2341. must use a device driver reference number of –10 for the .MPP driver.
  2342.  
  2343. Parameters
  2344.  
  2345. ioResult
  2346. The result of the function. When you execute the function asynchronously, the
  2347. function sets this parameter to 1 and returns a function result of noErr as soon
  2348. as the function begins execution. When the function completes execution, it sets
  2349. the ioResult parameter to the actual result code. 
  2350.  
  2351. csCode
  2352. Routine selector, automatically set by the MPW interface. Always equal to
  2353. PGetAppleTalkInfo for this function.
  2354.  
  2355. version
  2356. The version number of the PGetAppleTalkInfo function you are calling. For
  2357. version number 53 of the .MPP driver, this number is always 1.
  2358.  
  2359. varsPtr
  2360. A pointer to the MPP global variables. The MPP global variables are discussed in
  2361. “Protocol Handlers and Socket Listeners” in Chapter 10 of Volume II.
  2362.  
  2363. dcePtr
  2364. A pointer to the device control entry (DCE) data structure for the .MPP driver.
  2365. The DCE is described in the Device Manager chapters of Volumes II and V.
  2366.  
  2367. portID
  2368. The port number for the .MPP driver. The port number is always 0 unless you are
  2369. requesting information for an .MPP driver being used by a router.
  2370.  
  2371. configuration
  2372. A 32-bit long word of configuration flags. The following flags are currently
  2373. defined:
  2374.  
  2375. Bit  Flag       Description
  2376. 31   SrvAdrBit  TRUE (1) if the routine that opened the .MPP driver requested a
  2377. server node number. Server node numbers are described in the AppleTalk Manager
  2378. of Volume V. This flag indicates only that the server-node number was requested,
  2379. not that it was returned. Some AppleTalk devices, such as EtherTalk, do not
  2380. honor a request for a server-node number.
  2381.  
  2382. 30   RouterBit  TRUE (1) if an AppleTalk Internet Router was loaded at system
  2383. startup (that is, there's a router operating on the same node as your
  2384. application). A router can be loaded but not active.
  2385.  
  2386. 15   ExtendedBit  TRUE (1) if the node is on an extended network.
  2387.  
  2388. 7    BadZoneHintBit  TRUE (1) if the zone name of the node you are on was not
  2389. the same as the zone name stored in parameter RAM (sometimes referred to as the
  2390. zone name hint) when the .MPP driver was opened. If the zone name hint is
  2391. invalid, then the AppleTalk Manager uses the default zone for the network.
  2392.  
  2393. 6    OneZoneBit  TRUE (1) if only one zone is assigned to your extended network
  2394. or if you are not on an extended network.
  2395.  
  2396. selfSend
  2397. This parameter is nonzero if the ability of a node to send packets to itself is
  2398. enabled. Use the PSetSelfSend function, described in the AppleTalk Manager
  2399. chapter of Volume V, to enable or disable this feature.
  2400.  
  2401. netLo
  2402. The low value of the range of network numbers on the local cable. Only extended
  2403. networks can have a range of network numbers. For a nonextended network, this
  2404. parameter returns the network number.
  2405.  
  2406. netHi
  2407. The high value of the range of network numbers on the local cable. Only extended
  2408. networks can have a range of network numbers. For a nonextended network, this
  2409. parameter returns the network number.
  2410.  
  2411. ourAddr
  2412. The 24-bit AppleTalk network address of the node you are on. The least
  2413. significant byte of the longword is the node ID. The middle 16 bits are the
  2414. network number. The most significant byte of the longword is reserved for use by
  2415. Apple Computer, Inc. 
  2416.  
  2417. routerAddr
  2418. The 24-bit AppleTalk network address of the last router from which your node
  2419. heard traffic. The least significant byte of the longword is the node ID. The
  2420. middle 16 bits are the network number. The most significant byte of the longword
  2421. is reserved for use by Apple Computer, Inc. You should always use this address
  2422. when you want to communicate with a router.
  2423.  
  2424. numOfPHs
  2425. The maximum number of protocol handlers that this .MPP driver allows.
  2426.  
  2427. numOfSkts
  2428. The maximum number of statically assigned sockets that this .MPP driver allows.
  2429. Statically assigned sockets are described in Inside AppleTalk.
  2430.  
  2431. numNBPEs
  2432. The maximum number of concurrent requests to NBP that this .MPP driver allows. 
  2433.  
  2434. ntQueue
  2435. A pointer to the first entry in the names table for the local node. You can use
  2436. NBP routines to look up and register names in the names table. The names table
  2437. is described in “Name-Binding Protocol” in Chapter 10 of Volume II.
  2438.  
  2439. laLength
  2440. When you call the PGetAppleTalkInfo function on a node on an extended network,
  2441. you use this parameter to specify the number of bytes of the data link address
  2442. the function should place in the buffer pointed to by the LinkAddr parameter. If
  2443. you request more bytes than the total number of bytes in the address, then the
  2444. function returns in the laLength parameter the actual number of bytes it placed
  2445. in the buffer. If the address is longer than the size of the buffer, then the
  2446. PGetAppleTalkInfo function fills the buffer and returns in the laLength
  2447. parameter the actual length of the address, not the number of bytes returned.
  2448. The function does not return an error when the buffer is too large or too small
  2449. for the address.
  2450.  
  2451. linkAddr
  2452. A pointer to a buffer for the data link address returned for extended networks
  2453. only. You use the laLength parameter to specify the number of bytes of the
  2454. address that you want placed in this buffer. You must allocate a buffer large
  2455. enough to hold the number of bytes you specify. Speficy NIL for this parameter
  2456. if you do not want the function to provide a data-link address.
  2457.  
  2458. zoneName
  2459. A pointer to a buffer into which the PGetAppleTalkInfo function places the local
  2460. node’s zone name. You must allocate a buffer of at least 33 bytes to hold this
  2461. data, or specify NIL for the ZoneName parameter if you do not want to obtain the
  2462. zone name. This field is returned only if the node is on an extended network.
  2463.  
  2464. Result codes
  2465. noErr  0  no error
  2466. _______________________________________________________________________________
  2467.  
  2468. æKY A…New…NBP…Wildcard…Character
  2469. æC »A New NBP Wildcard Character                                         AppleTalk Manager
  2470. _______________________________________________________________________________
  2471.  
  2472. The Name-Binding Protocol (NBP) allows the use of certain wildcard characters in
  2473. AppleTalk names. You can use a wildcard character in a call to the PLookupName
  2474. function, for example, to obtain names and addresses of all the entities in a
  2475. given zone. NBP now supports the following wildcard characters:
  2476.  
  2477. NBP Wildcard characters
  2478.  
  2479. =  All possible values. This character can be used alone instead of a name in
  2480.    the object or type fields.
  2481.  
  2482. *  This zone. This character can be used alone instead of the zone name for the 
  2483.    local zone only.
  2484.  
  2485. ≈   Any or no characters in this position. This character can be used to obtain
  2486.     matches for object or type fields. For example, pa≈l matches pal, paul, 
  2487.     paper ball, and so forth. You can use only one double tilde (≈) character in
  2488.     any string. Press option-x to type the double tilde character on a Macintosh
  2489.     keyboard. If you use the double tilde character alone, it has the same 
  2490.     meaning as the equal sign (=). Note that any node not running AppleTalk
  2491.     Phase 2 drivers will not recognize this character.
  2492.  
  2493. _______________________________________________________________________________
  2494.  
  2495. æKY The…LAP…Manager
  2496. æC »THE LAP MANAGER                                                      AppleTalk Manager
  2497. _______________________________________________________________________________
  2498.  
  2499. The LAP Manager is a set of operating system utilities that provide a standard
  2500. interface between the AppleTalk protocols and the various link access protocols,
  2501. such as EtherTalk (ELAP), TokenTalk (TLAP), and LocalTalk (LLAP). Because the
  2502. LAP Manager is running even when the .MPP driver is not open, the LAP Manager
  2503. maintains the AppleTalk Transition Queue. The LAP Manager also contains protocol
  2504. handlers for certain types of 802.2 packets. This section describes the
  2505. AppleTalk Transition Queue and the LAP Manager 802.2 protocol handler, tells you
  2506. how to add or remove an AppleTalk Transition Queue entry, and describes how to
  2507. attach or detach your own 802.2 protocol handler.
  2508.  
  2509. _______________________________________________________________________________
  2510.  
  2511. æKY The…AppleTalk…Transition…Queue
  2512. æC »The AppleTalk Transition Queue                                       AppleTalk Manager
  2513. _______________________________________________________________________________
  2514.  
  2515. At any given time there might be two or more applications running that use
  2516. AppleTalk. If one of these applications opens or closes the AppleTalk drivers,
  2517. the other AppleTalk applications are affected. To ensure that your application
  2518. is not adversely affected by such an event, your application can place an entry
  2519. in the AppleTalk Transition Queue. The AppleTalk drivers send a message to each
  2520. application that is listed in the AppleTalk Transition Queue each time a routine
  2521.  
  2522.   •   opens the .MPP driver
  2523.   •   closes the .MPP driver
  2524.   •   indicates that it intends to close the .MPP driver
  2525.   •   denies permission to close the .MPP driver
  2526.   •   cancels its intention to close the .MPP driver
  2527.  
  2528. Each of these events is referred to as an AppleTalk transition.
  2529.  
  2530. Because opening or closing the .MPP driver opens or closes the .ATP and .XPP
  2531. drivers as well, and bacause the .MPP driver must be open before an application
  2532. can open the .DSP driver, knowing the status of the .MPP driver is tantamount to
  2533. knowing the status of all AppleTalk drivers.
  2534.  
  2535. Because the .MPP driver is not necessarily open when the AppleTalk Transition
  2536. Queue must be called, the LAP Manager maintains the queue. Each entry in the
  2537. AppleTalk Transition Queue is defined by the ATQentry record type.
  2538.  
  2539. TYPE ATQentry = RECORD
  2540.    qLink:     ATQentryPtr;  {next queue entry}
  2541.    qType:     INTEGER;      {unused}
  2542.    CallAddr:  ProcPtr;      {pointer to your routine}
  2543. END;
  2544.  
  2545. ATQentryptr = ^ATQentry;
  2546.  
  2547. When you want to add an entry to the AppleTalk Transition Queue, you must create
  2548. an ATQentry record and give the LAP Manager a pointer to this record. The qLink
  2549. field is a pointer to the next queue entry. You should set this field to NIL;
  2550. the LAP Manager fills it in when an application adds another entry to the queue.
  2551. The qType field is not used, but is present to maintain consistency with other
  2552. operating system queues . The CallAddr field is a pointer to a routine that you
  2553. provide. Your routine must handle the AppleTalk transition routines described in
  2554. “How the AppleTalk Manager Calls Your AppleTalk Transition Queue Routine” later
  2555. in this chapter.
  2556.  
  2557. Because you allocate the memory for the AppleTalk Transition Queue entry, you
  2558. can add as many fields to the end of the entry as you wish for your own
  2559. purposes. Whenever your routine is called, the caller provides you with a
  2560. pointer to the queue entry so that you can have access to the information you
  2561. stored at the end of your queue entry.
  2562.  
  2563. _______________________________________________________________________________
  2564.  
  2565. æKY Adding…and…Removing…AppleTalk…Transition…Queue…Entries
  2566. æC »Adding and Removing AppleTalk Transition Queue Entries               AppleTalk Manager
  2567. _______________________________________________________________________________
  2568.  
  2569. There are three LAP Manager procedures you can use that are related to the
  2570. AppleTalk Transition Queue:
  2571.  
  2572.   •   The LAPAddATQ procedure adds an entry to the AppleTalk Transition Queue.
  2573.       You provide in the A0 register a pointer to an ATQentry record. The
  2574.       CallAddr field of the ATQentry record holds a pointer to your routine.
  2575.       The LAP Manager fills in the qLink field with a pointer to the next queue
  2576.       entry.
  2577.  
  2578.   •   The LAPRmvATQ procedure removes an entry from the AppleTalk Transition
  2579.       Queue. You provide in the A0 register a pointer to your queue entry.
  2580.  
  2581.   •   The LAPGetATQ procedure returns in the A1 register a pointer to the
  2582.       AppleTalk Transition Queue header.
  2583.  
  2584. Assembly-language note:  From assembly language, you call LAP Manager routines
  2585. by placing a routine selector in the D0 register and executing a JSR instruction
  2586. to an offset 2 bytes past the start of the LAP manager. Before you call the
  2587. LAPAddATQ or LAPRmvATQ routines, you must also place a pointer to your AppleTalk
  2588. Transition Queue entry in the A0 register. The LAPGetATQ routine returns a
  2589. pointer to the AppleTalk Transition Queue header in the A1 register. 
  2590. Here is an assembly-language call to a LAP Manager routine:
  2591.  
  2592. LAPMgrPtr   EQU  $B18  ;Entry point for LAP Manager
  2593. LAPMgrCall  EQU  2     ;Offset to LAP Manager routines
  2594. ATQEntry    EQU  *     ;AppleTalk Transition Queue entry
  2595. ...
  2596.  
  2597.     MOVEQ #Code,D0       ;Place routine selector in D0
  2598.     MOVE.L LAPMgrPtr,An  ;Put LAP Mgr entry pt in An
  2599.     MOVE.L ATQEntry,A0   ;Put ATQ entry in A0 (LAPAddATQ & LAPRmvATQ only)
  2600.     JSR  LAPMgrCall(An)  ;Jump to start of LAP Mgr routines
  2601.  
  2602. You can use LAP Manager routines to add an entry to the AppleTalk Transition
  2603. Queue, remove an entry from the queue, or obtain a pointer to the AppleTalk
  2604. Transition Queue header. See “Using the AppleTalk Transition Queue,” earlier in
  2605. this chapter, for a description of the queue and how to use it.
  2606.  
  2607. PROCEDURE LAPAddATQ (entryPtr: pointer);
  2608.  
  2609. On entry  D0: 23
  2610.           A0: pointer to ATQentry record
  2611.  
  2612. The LAPAddATQ procedure adds an entry to the AppleTalk Transition Queue. The
  2613. entryPtr parameter is a pointer to an ATQentry record. The ATQentry record
  2614. includes a pointer to the routine that AppleTalk calls when any routine opens or
  2615. closes the .MPP driver, or indicates that it intends to close the .MPP driver.
  2616. The ATQentry is described in “Using the AppleTalk Transition Queue” earlier in
  2617. this chapter.
  2618.  
  2619. PROCEDURE LAPRmvATQ (entryPtr: pointer);
  2620. \
  2621. On entry  D0: 24
  2622.           A0: pointer to ATQentry record
  2623.  
  2624. The LAPRmvATQ procedure removes an entry from the AppleTalk Transition Queue.
  2625. The entryPtr parameter is a pointer to an ATQentry record. 
  2626.  
  2627. PROCEDURE LAPGetATQ (VAR eqPtr: pointer);
  2628.  
  2629. On entry  D0: 25
  2630. On exit  A1: pointer to AppleTalk Transition Queue header
  2631.  
  2632. The LAPGetATQ procedure returns a pointer to the AppleTalk Transition Queue
  2633. header.
  2634. _______________________________________________________________________________
  2635.  
  2636. æKY Sending…Messages…to…the…AppleTalk…Transition…Queue
  2637. æC »Sending Messages to the AppleTalk Transition Queue                   AppleTalk Manager
  2638. _______________________________________________________________________________
  2639.  
  2640. Whereas it is unlikely that opening the .MPP driver will adversely affect
  2641. another program, an application should never close the .MPP driver, because
  2642. another program might be using it. Under certain circumstances, however, the
  2643. system might close the .MPP driver, provided no application objects. The system
  2644. uses the .MPP driver’s PATalkClosePrep function to inform each routine in the
  2645. AppleTalk Transition Queue that it intends to close the .MPP driver, giving each
  2646. routine in the queue the opportunity to deny permission to do so.
  2647.  
  2648. The system provides a pointer to a 255-byte buffer when it calls the
  2649. PATalkClosePrep function. If any routine in the AppleTalk Transition Queue
  2650. denies permission to close the .MPP driver, it places a name in the buffer and
  2651. returns control to the AppleTalk Manager. The name that the routine places in
  2652. the buffer should be the name of the application that placed the entry in the
  2653. queue. The PATalkClosePrep function then calls each routine in the AppleTalk
  2654. Transition Queue a second time to inform it that the request to close the .MPP
  2655. driver has been canceled. If any routine in the AppleTalk Transition Queue
  2656. denies permission to close the .MPP driver, the PATalkClosePrep function returns
  2657. the result code closeErr.
  2658.  
  2659. If any routine denies permission to close the .MPP driver, the system displays a
  2660. dialog box informing the user that another application is using the .MPP driver,
  2661. and showing the name that the AppleTalk Transition Queue routine placed in the
  2662. buffer. The dialog box gives the user the option of canceling the request to
  2663. close AppleTalk, or of closing AppleTalk anyway. 
  2664.  
  2665. Note:  If the user chooses to close AppleTalk despite the fact that an
  2666. application is using it, the system calls the MPPClose function. AppleTalk calls
  2667. each application in the AppleTalk Transition Queue again, this time informing it
  2668. that AppleTalk is about to close. In this case, your AppleTalk Transition Queue
  2669. routine must prepare for the imminent closing of AppleTalk; it cannot deny
  2670. permission to the MPPClose function.
  2671.   
  2672. FUNCTION PATalkClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  2673.  
  2674. Parameter block
  2675.   Æ  26  csCode  word  always PATalkClosePrep
  2676.   Æ      appName  pointer  buffer for name of application that denies request
  2677.  
  2678. The PATalkClosePrep function calls each routine listed in the AppleTalk
  2679. Transition Queue to request permission to close the .MPP driver. 
  2680. The routine that calls the PATalkClosePrep function must allocate a 255-byte
  2681. buffer and provide a pointer to it in the appName parameter. If a routine in the
  2682. AppleTalk Transition Queue denies permission to close the .MPP driver, that
  2683. routine places a name in the buffer pointed to by the appName parameter, and the
  2684. AppleTalk Manager calls each routine in the AppleTalk Transition Queue a second
  2685. time to inform it that the request to close the .MPP driver has been canceled.
  2686. The PATalkClosePrep function then returns the result code closeErr, indicating
  2687. that the calling routine may not close the .MPP driver. The csCode parameter is
  2688. a routine selector; it is always equal to PATalkClosePrep for this function.
  2689.  
  2690. Result codes
  2691. noErr       0  no error
  2692. closeErr  –24  permission to close .MPP driver was denied
  2693.  
  2694. The system can use the PCancelATClosePrep function to undo the effects of the
  2695. PATalkClosePrep function. The system uses this function, for example, if some
  2696. condition prevents it from closing the .MPP driver even though each routine
  2697. listed in the AppleTalk Transition Queue gave permission to close it. When the
  2698. system calls the PCancelATClosePrep function, the AppleTalk Manager calls each
  2699. routine in the AppleTalk Transition Queue to inform it that the request to close
  2700. the .MPP driver has been canceled.
  2701.  
  2702. FUNCTION PCancelATClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  2703.  
  2704. Parameter block
  2705.   Æ  26  csCode  word  always PCancelATClosePrep 
  2706.  
  2707. The PCancelATClosePrep function undoes the effects of the PATalkClosePrep
  2708. function. The PCancelATClosePrep function calls each routine in the AppleTalk
  2709. Transition Queue to inform it that the request to close the .MPP driver has been
  2710. canceled. 
  2711.  
  2712. The operating system uses this function, for example, if some condition prevents
  2713. it from closing the .MPP driver even though each routine listed in the AppleTalk
  2714. Transition Queue gave permission to close it. 
  2715.  
  2716. The csCode parameter is a routine selector, always equal to PCancelATClosePrep
  2717. for this function.
  2718.  
  2719. Result codes
  2720. noErr  0  no error
  2721. _______________________________________________________________________________
  2722.  
  2723. æKY How…the…AppleTalk…Manager…Calls…Your…Transition…Queue…Routine
  2724. æC »How the AppleTalk Manager Calls Your Transition Queue Routine        AppleTalk Manager
  2725. _______________________________________________________________________________
  2726.  
  2727. When you have used the LAPAddATQ function to add an entry to the AppleTalk
  2728. Transition Queue, the AppleTalk Manager calls your routine when any of the
  2729. following AppleTalk transitions occurs:
  2730.  
  2731.   •   A routine opens the .MPP driver. 
  2732.   •   A routine closes the .MPP driver. 
  2733.   •   A routine calls the ATalkClosePrep function. 
  2734.   •   One of the routines in the AppleTalk Transition Queue denies permission
  2735.       for the routine that called the ATalkClosePrep function to close
  2736.       AppleTalk, or a routine executes the PCancelATClosePrep function.
  2737.  
  2738. When the AppleTalk Manager calls your AppleTalk Transition Queue routine, the
  2739. first item on the stack (after the return address) is a routine selector. There
  2740. is one routine selector for each type of transition:
  2741.  
  2742. Routine selector  Transition
  2743.   0               .MPP driver opened
  2744.   2               .MPP driver about to close
  2745.   3                ATalkClosePrep function has been called
  2746.   4                Closing of .MPP driver has been canceled
  2747.  
  2748. The interface between the AppleTalk Transition Queue and your routine follows
  2749. the conventions of the C language: Your routine must preserve all registers
  2750. except D0, D1, D2, A0 and A1; all parameters are passed on the stack as long
  2751. words.
  2752.  
  2753. Note:  Because the number of parameters that an AppleTalk Transition Queue
  2754. routine must read off the stack varies with the routine selector, and because
  2755. the routine must be able to place a value in the D0 register, you cannot use
  2756. Pascal to write an AppleTalk Transition Queue routine.
  2757.  
  2758. When an application calls the MPPOpen function to open the .MPP driver, the
  2759. AppleTalk Manager calls every routine listed in the AppleTalk Transition Queue
  2760. after it opens the .MPP driver. When the AppleTalk Manager calls your AppleTalk
  2761. Transition Queue routine to tell it that the .MPP driver has been opened, the
  2762. stack looks like this:
  2763.  
  2764. SP Æ   Return address (4 bytes)
  2765.        Routine selector; 0 when .MPP opens (4 bytes)
  2766.        Pointer to AppleTalk Transition Queue entry (4 bytes)
  2767.        Pointer to Device Manager’s parameter block (4 bytes)
  2768.        previous contents
  2769.  
  2770. If the .MPP driver is already open and a routine executes the MPPOpen function,
  2771. the AppleTalk Manager does not call the routines in the AppleTalk Transition
  2772. Queue.
  2773.  
  2774. You can use the pointer to your routine’s entry in the AppleTalk Transition
  2775. Queue to get access to any fields at the end of the queue entry that you
  2776. allocated for your own use. The last item on the stack is a pointer to the start
  2777. of the Device Manager extended parameter block used by the routine that opened
  2778. the .MPP driver. This pointer is provided for your information only; you must
  2779. not change any of the fields in this parameter block. 
  2780.  
  2781. Your AppleTalk Transition Queue routine can perform any tasks you wish in
  2782. response to the notification that the .MPP driver has been opened, such as using
  2783. NBP to register a name on the internet. 
  2784.  
  2785. When any routine calls the MPPClose function to close the .MPP driver, the
  2786. AppleTalk Manager calls every routine listed in the AppleTalk Transition Queue
  2787. before the .MPP driver closes. When the AppleTalk Manager calls your routine to
  2788. tell it that the .MPP driver is about to close, the stack looks like this:
  2789.  
  2790.  
  2791. SP Æ  Return address (4 bytes)
  2792.        Routine selector; 2 when .MPP is about to close (4 bytes)
  2793.        Pointer to AppleTalk Transition Queue entry (4 bytes)
  2794.        previous contents
  2795.  
  2796. If the .MPP driver is already closed and a routine executes the MPPClose
  2797. function, the AppleTalk Manager does not call the routines in the AppleTalk
  2798. Transition Queue.
  2799.  
  2800. You can use the pointer to your routine’s entry in the AppleTalk Transition
  2801. Queue to get access to any fields at the end of the queue entry that you
  2802. allocated for your own use.
  2803.  
  2804. Your routine can perform any tasks you wish to prepare for the imminent closing
  2805. of AppleTalk, such as ending a session with a remote terminal and informing the
  2806. user that the connection is being closed. You must return control to the
  2807. AppleTalk Manager as quickly as possible. When the AppleTalk Manager calls your
  2808. routine with a routine selector of 2, you cannot prevent the .MPP driver from
  2809. closing.
  2810.  
  2811. When a routine calls the ATalkClosePrep function to inform the AppleTalk Manager
  2812. that it wants to close the .MPP driver, the AppleTalk Manager calls every
  2813. routine listed in the AppleTalk Transition Queue to request permission to close
  2814. the .MPP driver. When the AppleTalk Manager calls your routine to request
  2815. permission to close the .MPP driver, the stack looks like this:
  2816.  
  2817.  
  2818. SP Æ  Return address (4 bytes)
  2819.        Routine selector; 3 to ask permission to close .MPP (4 bytes)
  2820.        Pointer to AppleTalk Transition Queue entry (4 bytes)
  2821.        Pointer to pointer to name of client (4 bytes)
  2822.        previous contents
  2823.  
  2824. Your routine can return either a longword of zeros in the D0 register,
  2825. indicating that it accepts the request to close, or a nonzero value in the D0
  2826. register, indicating that it denies the request to close. 
  2827. You can use the pointer to your routine’s entry in the AppleTalk Transition
  2828. Queue to get access to any fields at the end of the queue entry that you
  2829. allocated for your own use.
  2830.  
  2831. The last parameter on the stack is a pointer to the clientName field (offset 28)
  2832. in the .MPP driver parameter block that was used by the routine that called the
  2833. PATalkClosePrep function. This field contains a pointer to a 255-byte buffer. If
  2834. you intend to deny the request to close AppleTalk, you should place a string in
  2835. this buffer containing the name of your application. The routine that called the
  2836. PATalkClosePrep function can then display a dialog box telling the user the name
  2837. of the application that is currently using AppleTalk.
  2838.  
  2839. Because the AppleTalk Manager calls your routine again (with the routine
  2840. selector set to 2) before the .MPP driver actually closes, it is not necessary
  2841. for your routine to do anything other than grant or deny permission in response
  2842. to being called with the routine selector set to 3. However, you might want to
  2843. prohibit the users from opening new sessions or establishing new connections
  2844. while you are waiting for the .MPP driver to close.
  2845.  
  2846. When a routine calls the PCancelATClosePrep function to cancel the effects of
  2847. the PATalkClosePrep function, or when any routine in the AppleTalk Transition
  2848. Queue denies permission for the .MPP driver to close, the AppleTalk Manager
  2849. calls every routine listed in the AppleTalk Transition Queue to inform it that
  2850. the request to close the .MPP driver has been canceled. When the AppleTalk
  2851. Manager calls your AppleTalk Transition Queue routine to cancel a request to
  2852. close the .MPP driver, the stack looks like this:
  2853.  
  2854.  
  2855. SP Æ  Return address (4 bytes)
  2856.        Routine selector; 4 to cancel a close (4 bytes)
  2857.        Pointer to AppleTalk Transition Queue entry (4 bytes)
  2858.        previous contents
  2859.  
  2860. You can use the pointer to your routine’s entry in the AppleTalk Transition
  2861. Queue to get access to any fields at the end of the queue entry that you
  2862. allocated for your own use.
  2863.  
  2864. If your routine performed any tasks to prepare for the closing of AppleTalk, it
  2865. should reverse their effects when it is called with the routine selector set to
  2866. 4.
  2867.  
  2868. Listing 29-1 illustrates the use of the AppleTalk Transition Queue. It defines a
  2869. routine that AppleTalk is to call when an AppleTalk transition occurs. This
  2870. routine first checks the stack to determine why it is being called, and then
  2871. acts accordingly. If the routine selector indicates that the .MPP driver has
  2872. just opened, the listing uses NBP to register a name on the internet. If the
  2873. .MPP driver is about to close, the routine calls ADSP to close the session and
  2874. displays a dialog box informing the user that the session is being closed. If
  2875. some application is asking permission to close the .MPP driver, the routine
  2876. checks to see if your application has an open ADSP session. If your application
  2877. has a current open ADSP session, the routine places the name of your application
  2878. in the buffer provided by the client that called the PATalkClosePrep function,
  2879. and places a 0 in the D0 register. If your application has no open ADSP session,
  2880. the routine places a 1 in the D0 register. If AppleTalk is canceling a request
  2881. to close the .MPP driver, the routine terminates without further action. 
  2882. Listing 29-1 also defines an entry to the AppleTalk Transition Queue that points
  2883. to the routine, and calls the LAPAddATQ procedure to add this entry to the
  2884. queue. 
  2885.  
  2886. Listing 29-1.  Using the AppleTalk Transition Queue (TO BE PROVIDED)
  2887.  
  2888. _______________________________________________________________________________
  2889.  
  2890. æKY The…LAP…Manager…802.2…Protocol
  2891. æC »The LAP Manager 802.2 Protocol                                       AppleTalk Manager
  2892. _______________________________________________________________________________
  2893.  
  2894. The Institute of Electrical and Electronics Engineers (IEEE) has defined a
  2895. series of communication protocols for use on a variety of networks. At the
  2896. hardware and signaling level, these protocols include the 802.3 Ethernet
  2897. protocol, the 802.4 Token Bus protocol, and the 802.5 Token Ring protocol. At
  2898. the link access level, these protocols are all handled by another IEEE protocol,
  2899. the 802.2 protocol. The AppleTalk LAP Manager includes two routines that allow
  2900. you to attach and detach protocol handlers for 802.2 Type 1 data packets: the
  2901. L802Attach and L802Detach routines. You can write an application that reads
  2902. 802.2 Type 1 data packets, and use the L802Attach routine to install your
  2903. application as a client of the LAP Manager. The ANSI/IEEE standards for the 802
  2904. protocols are published by the Institute of Electrical and Electronics
  2905. Engineers.
  2906.  
  2907. The first 14 bytes of a packet sent or received by the .ENET driver are the
  2908. header. The first 12 bytes consist of the destination and source data link
  2909. addresses (such as the Ethernet hardware addresses). If the value of the last
  2910. two bytes in the header is greater than 1500, then the .ENET driver treats that
  2911. field as an Ethernet protocol type discriminator. See “The .ENET Driver,” later
  2912. in this chapter, for more information on Ethernet protocols. If the value of the
  2913. last two bytes in the header is less than 1500, then the packet is an 802.3
  2914. protocol packet and the .ENET driver passes it to the LAP Manager.
  2915.  
  2916. The LAP Manager receives the entire 802.3 packet from the .ENET driver. The
  2917. first three bytes of the 802.3 data constitues the header for the 802.2
  2918. protocol. The first byte of the 802.2 header is known as the destination service
  2919. access point (DSAP). If the DSAP type field is equal to $AA, then the first five
  2920. bytes of the 802.2 data constitutes a protocol discriminator known as the
  2921. subnetwork access protocol (SNAP) type. If the SNAP type field is $00000080F3,
  2922. indicating the AppleTalk Address Resolution Protocol (AARP), then the next four
  2923. bytes of the 802.2 data constitutes a third type field, the AARP packet type.
  2924. AARP is discussed in Inside AppleTalk.
  2925.  
  2926. The following data packet header, for example, indicates an Ethernet packet
  2927. containing AppleTalk data. The .ENET driver would deliver this packet to the
  2928. AppleTalk Phase 1 device drivers.
  2929.  
  2930. 02608C010203 02608C040506 809B
  2931.  
  2932. By contrast, the following data packet header indicates an 802.3 packet
  2933. containing AppleTalk data. The .ENET driver would deliver this packet to the
  2934. AppleTalk Phase 2 LAP Manager
  2935.  
  2936. 02608C010203 02608C040506 0060 AA AA 03 080007809B
  2937.  
  2938. Similarly, the following data packet header indicates an 802.3 packet to be
  2939. delivered to the EtherTalk AARP handler:
  2940.  
  2941. 02608C010203 02608C040506 0060 AA AA 03 00000080F3 0001809B
  2942.  
  2943. When you call the L802Attach function, you provide a pointer to your protocol
  2944. handler, the reference number of the .ENET driver, and a pointer to a string
  2945. containing one or more type fields. The type fields indicate the DSAP value and
  2946. any other protocol type fields (such as the SNAP type and the AARP type). The
  2947. LAP Manager delivers to your protocol handler any 802.2 data packets that have
  2948. the protocol type you specify. 
  2949. _______________________________________________________________________________
  2950.  
  2951. æKY Attaching…and…Detaching…802.2…Protocol…Handlers
  2952. æC »Attaching and Detaching 802.2 Protocol Handlers                      AppleTalk Manager
  2953. _______________________________________________________________________________
  2954.  
  2955. You can attach to the LAP Manager your own protocol handler for 802.2 protocols.
  2956. The LAP Manager has permanent handlers for certain types of EtherTalk packets.
  2957. You cannot replace or override the permanent LAP Manager protocol handlers.
  2958.  
  2959. FUNCTION L802Attach (Eref: word; handlerPtr: procptr; ProtType: pointer) :
  2960. OSErr;
  2961.  
  2962.  
  2963. On entry  D0: 21
  2964.           D2: reference number of .ENET driver
  2965.           A0: pointer to your protocol handler
  2966.           A1: pointer to protocol specification
  2967.  
  2968. On exit   D0: nonzero if error
  2969.  
  2970. The L802Attach function attaches to the LAP Manager a protocol handler for a
  2971. specific IEEE 802.2 protocol type.
  2972.  
  2973. The Eref parameter is the reference number of the .ENET driver that was returned
  2974. by the OpenSlot function when you or somone else opened the .ENET driver. If you
  2975. are not using the .ENET driver or a driver that uses the same interface as the
  2976. .ENET driver, you cannot use the L802Attach function. The handlerPtr parameter
  2977. is a pointer to your protocol handler.
  2978.  
  2979. The ProtType parameter is a pointer to the protocol type specification for this
  2980. protocol handler. The protocol type specification consists of one or more
  2981. protocol type fields, each preceded by a length byte. The LAP Manager reads the
  2982. protocol type fields in the 802.2 data packet header to determine to which
  2983. protocol handler (if any) to deliver the packet. The first type field in your
  2984. protocol specification is 1 byte long and is known as the destination service
  2985. access point (DSAP). If the DSAP type field is equal to $AA, then the protocol
  2986. type specification can contain a second type field, the 5-byte subnetwork access
  2987. protocol (SNAP) type. If the SNAP type field is $00000080F3, indicating the
  2988. AppleTalk Address Resolution Protocol (AARP), then the protocol type
  2989. specification can contain a third type field, the 4-byte AARP protocol type.
  2990. Terminate the list of protocol type fields with a byte of zeros.
  2991.  
  2992. The following protocol type specification, for example, indicates an 802.3
  2993. packet containing AppleTalk data. The .ENET driver would deliver this packet to
  2994. the AppleTalk Phase 2 LAP Manager. The first byte, $01, is the length byte for
  2995. the first protocol type field (the DSAP type field), $AA. The third byte, $05,
  2996. is the length byte for the next protocol type field, the SNAP. The final byte 
  2997. ($00) terminates the type specification.
  2998.  
  2999. 01 AA 05 08 00 07 80 9B 00
  3000.  
  3001. The following protocol type specification indicates an 802.3 packet to be
  3002. delivered to the EtherTalk AARP handler: Notice that the SNAP field is followed
  3003. by an additional type field, the AARP protocol type.
  3004.  
  3005. 01 AA 05 00 00 00 80 F3 04 00 01 80 9B 00
  3006.  
  3007. See the ANSI/IEEE standard 802.2 for more information about 802.2 protocols, and
  3008. Inside AppleTalk for more information about AARP.
  3009.  
  3010. Result codes
  3011. noErr  0  no error
  3012.  
  3013. FUNCTION L802Detach (Eref: word; ProtType: pointer) : OSErr;
  3014.  
  3015. On entry  D0: 22
  3016.           D2: reference number of .ENET driver
  3017.           A1: pointer to protocol specification
  3018.  
  3019. On exit   D0: nonzero if error
  3020.  
  3021. The L802Detach function detaches from the LAP Manager a protocol handler for a
  3022. specific IEEE 802.2 protocol type.
  3023.  
  3024. The Eref parameter is the reference number of the .ENET driver that was returned
  3025. by the OpenSlot function when you or somone else opened the .ENET driver. The
  3026. handlerPtr parameter is a pointer to your protocol handler.
  3027.  
  3028. The ProtType parameter is a pointer to the protocol type specification for this
  3029. protocol handler. You must specify exactly the same protocol type as you
  3030. specified for the L802Attach function when you attached the protocol handler.
  3031.  
  3032. Result codes
  3033. noErr  0  no error
  3034. _______________________________________________________________________________
  3035.  
  3036. æKY AppleTalk…Data…Stream…Protocol…(ADSP)
  3037. æC »APPLETALK DATA STREAM PROTOCOL (ADSP)                                AppleTalk Manager
  3038. _______________________________________________________________________________
  3039.  
  3040. One of the significant new features of AppleTalk introduced with AppleTalk Phase
  3041. 2 is the AppleTalk Data Stream Protocol (ADSP), which provides a full-duplex
  3042. data stream connection between two nodes in the AppleTalk internet. Like the
  3043. AppleTalk Session Protocol, Printer Access Protocol, and AppleTalk Transaction
  3044. Protocol, ADSP uses the Datagram Delivery Protocol to send its data over the
  3045. internet. Therefore, even though ADSP appears to its clients to handle data as a
  3046. stream of bytes, the data is actually transmitted and received by DDP in
  3047. packets. ADSP takes advantage of this fact by including control and status
  3048. information in the DDP packet header. You can use the .DSP driver functions
  3049. described in “.DSP Driver Functions,” later in this chapter, to control an ADSP
  3050. connection. The 
  3051. .DSP driver takes care of implementation of the ADSP protocol for you. To use 
  3052. ADSP, you must have the file named 'ADSP' in your system folder.
  3053.  
  3054. Every ADSP connection is between two sockets in the AppleTalk internet. Each
  3055. socket can establish simultaneous ADSP connections with several other sockets,
  3056. but there can be only one ADSP connection between any two sockets at one time.
  3057. When a pair of sockets establishes an ADSP connection, each socket client
  3058. initializes and maintains a certain amount of control and state information that
  3059. it uses for error checking and to synchronize communication with the other
  3060. socket client. 
  3061.  
  3062. The combination of a socket and the ADSP information maintained by the socket
  3063. client is referred to as a connection end. When two connection ends establish
  3064. communication, the connection is considered an open connection. When both
  3065. connection ends terminate the link and dispose of the connection information
  3066. each maintains, the connection is considered a closed connection. If one
  3067. connection end is established but the other connection end is unreachable or has
  3068. disposed of its connection information, the connection is considered a half-open
  3069. connection. No communication can occur over a half-open or closed connection. To
  3070. prevent a half-open connection from tying up resources, ADSP automatically
  3071. closes any half-open connection that cannot reestablish communications within
  3072. two minutes.
  3073.  
  3074. _______________________________________________________________________________
  3075.  
  3076. æKY Using…ADSP
  3077. æC »Using ADSP                                                           AppleTalk Manager
  3078. _______________________________________________________________________________
  3079.  
  3080. You can use the AppleTalk Data Stream Protocol to implement a data stream
  3081. connection between any two sockets on the internet. (Note that although there
  3082. can be only one ADSP connection between any two sockets, a single socket can
  3083. maintain connections with several other sockets.) This section describes how to
  3084. open, maintain, and close a connection between two sockets on an internet. It
  3085. also describes how to establish and use a connection listener; that is, a
  3086. connection end that waits passively to receive a connection request and then
  3087. passes the connection request on to its client, the connection server. Finally,
  3088. this section describes how to write a routine that ADSP calls when your
  3089. connection end receives an unsolicited connection event. 
  3090. _______________________________________________________________________________
  3091.  
  3092. æKY The…ADSP…Connection…Control…Block
  3093. æC »The ADSP Connection Control Block                                    AppleTalk Manager
  3094. _______________________________________________________________________________
  3095.  
  3096. When you establish an ADSP connection end, you must allocate a nonrelocatiable
  3097. block of memory for, and provide a pointer to, a data structure known as a
  3098. connection control block (CCB). The CCB is used by ADSP to store state
  3099. information about the connection end. You may read the fields in the CCB to
  3100. obtain information about the connection end, but you are not allowed to write to
  3101. any of the fields except one, the userFlags field. The connection control block
  3102. requires 242 bytes, and is defined by the TRCCB record.
  3103.  
  3104. TPCCB = ^TRCCB;
  3105.  
  3106. TRCCB = PACKED RECORD
  3107.   ccbLink:        TPCCB;                        {link to next CCB}
  3108.   refNum:         INTEGER;                      {user reference number}
  3109.   state:          INTEGER;                      {state of the connection end}
  3110.   userFlags:      Byte;                         {user flags for connection}
  3111.   localSocket:    Byte;                         {local socket number}
  3112.   remoteAddress:  AddrBlock;                    {remote end internet address}
  3113.   attnCode:       INTEGER;                      {attention code received}
  3114.   attnSize:       INTEGER;                      {size of attention data}
  3115.   attnPtr:        Ptr;                          {pointer to attention data}
  3116.   reserved:       PACKED ARRAY [1..220] OF Byte {reserved for use by ADSP}
  3117. END;
  3118.  
  3119. The internet address of the remote connection end is defined in the TRCCB record
  3120. by an AddrBlock record:
  3121.  
  3122. AddrBlock = PACKED RECORD
  3123.   aNet:     INTEGER;  {network number}
  3124.   aNode:    Byte;     {node ID}
  3125.   aSocket:  Byte;     {socket number}
  3126. END;
  3127.  
  3128. Field descriptions
  3129.  
  3130. ccbLink
  3131. Pointer to the next CCB. For use by ADSP only.
  3132.  
  3133. refnum
  3134. The reference number of the connection end. This number is assigned by ADSP when
  3135. you establish the connection end.
  3136.  
  3137. state
  3138. The state of the connection end, as follows:
  3139.  
  3140. State       Value  Meaning
  3141. sListening  1      Socket is a connection listening socket; that is, a socket
  3142. that accepts ADSP requests to open connections and passes them on to a socket
  3143. client. Ordinarily used only by servers.
  3144.  
  3145. sPassive    2  Socket client is inactive but capable of accepting an ADSP
  3146. request to open a connection. Unlike a connection listening socket, which passes
  3147. the open-connection request on to a routine that can establish the connection on
  3148. any socket, a socket client in the sPassive state can accept an open-connection
  3149. request only to establish itself as a connection end.
  3150.  
  3151. sOpening    3  Socket client has sent an open-connection request and is waiting
  3152. for acknowledgment.
  3153.  
  3154. sOpen       4  Connection is open.
  3155.  
  3156. sClosing    5  Socket client has requested that ADSP close the connection, and
  3157. ADSP is sending data or waiting for acknowledgement of data it has sent before
  3158. closing the connection. 
  3159.  
  3160. sClosed     6  Either connection end or ADSP has closed the connection.
  3161.  
  3162. userFlags
  3163. Flags that indicate an unsolicited connection event has occurred. An unsolicited
  3164. connection event is an event initiated by ADSP or the remote connection end that
  3165. is not in response to any .DSP function that you executed.  
  3166.  
  3167. Each time an unsolicited connection event occurs, ADSP sets a flag in the
  3168. userFlags field of the CCB and calls the routine you specified in the
  3169. userRoutine parameter to the dspInit command (if any). The user routine must
  3170. read the userFlags field and then clear the flag to 0. ADSP cannot notify your
  3171. routine of future events unless you clear the flag after each event.
  3172.  
  3173.  
  3174. ADSP recognizes four types of unsolicited connection events, one corresponding
  3175. to each of the flags in this field. The events and flags are defined as follows,
  3176. where bit 7 is the most significant bit:
  3177.  
  3178. Event    Flag Bit  Meaning
  3179. eClosed     7      ADSP has been informed by the remote connection end that the
  3180. remote connection end has closed the connection. 
  3181.  
  3182. eTearDown   6      ADSP has determined that the remote connection end is not
  3183. responding, and so has closed the connection. 
  3184.  
  3185. eAttention  5      ADSP has received an attention message from the remote
  3186. connection end. 
  3187.  
  3188. eFwdReset   4      ADSP has received a forward reset command from the remote
  3189. client end, has discarded all ADSP data not yet delivered— including the data in
  3190. the local client end’s receive queue—and has resynchronized the connection. 
  3191.  
  3192. none        3–0    Reserved
  3193.  
  3194. localSocket
  3195. The socket number through which DDP transmits and receives the ADSP packets.
  3196.  
  3197. remoteAddress
  3198. The internet address of the socket used by the remote connection end.
  3199.  
  3200. attnCode
  3201. The attention code received by ADSP when the remote connection end sends an
  3202. attention message.
  3203.  
  3204. attnSize
  3205. The size of the attention message received by ADSP when the remote connection
  3206. end sends an attention message.
  3207.  
  3208. attnPtr
  3209. A pointer to a buffer containing the attention message received by ADSP from the
  3210. remote connection end.
  3211.  
  3212. reserved
  3213. A data buffer reserved for use by ADSP.
  3214.  
  3215. _______________________________________________________________________________
  3216.  
  3217. æKY The….DSP…Parameter…Block
  3218. æC »The .DSP Parameter Block                                             AppleTalk Manager
  3219. _______________________________________________________________________________
  3220.  
  3221. The .DSP commands use the AppleTalk preferred interface. Each .DSP command
  3222. includes a pointer to a parameter block that includes all of the parameters
  3223. needed by that command. 
  3224.  
  3225. The .DSP parameter block is defined by the DSPParamBlock record.
  3226.  
  3227. DSPParamBlock = PACKED RECORD
  3228.   qLink:   QElemPtr;  {next queue entry}
  3229.   qType:   INTEGER;  {queue type}
  3230.   ioTrap:   INTEGER;  {routine trap}
  3231.   ioCmdAddr:   Ptr;  {routine address}
  3232.   ioCompletion:   ProcPtr;  {completion routine}
  3233.   ioResult:   OsErr;  {result code}
  3234.   ioNamePtr:   StringPtr;  {used only for Open routine}
  3235.   ioVRefNum:   INTEGER;  {volume reference number}
  3236.   ioCRefNum:   INTEGER;  {driver reference number}
  3237.   csCode:   INTEGER;  {primary command code}
  3238.   qStatus:  LONGINT;  {reserved for ADSP}
  3239.   ccbRefNum:  INTEGER;  {CCB reference number}
  3240.  
  3241.   CASE INTEGER OF
  3242.     dspInit,
  3243.     dspCLInit:
  3244.     (
  3245.       ccbPtr:  TPCCB;  {pointer to CCB}
  3246.       userRoutine:  ProcPtr;  {pointer to user routine}
  3247.       sendQSize:  INTEGER;  {size of send queue}
  3248.       sendQueue:  Ptr;  {pointer to send queue}
  3249.       recvQSize:  INTEGER;  {size of receive queue}
  3250.       recvQueue:  Ptr;  {pointer to receive queue}
  3251.       attnPtr:  Ptr;  {pointer to attention-message buffer}
  3252.       localSocket:  Byte;  {local socket number}
  3253.     );
  3254.  
  3255.     dspOpen,
  3256.     dspCLListen,
  3257.     dspCLDeny:
  3258.      (
  3259.       localCID:  INTEGER;  {local connection ID}
  3260.       remoteCID:  INTEGER;  {remote connection ID}
  3261.       remoteAddress:  AddrBlock;  {remote internet address}
  3262.       filterAddress:  AddrBlock;  {address filter}
  3263.       sendSeq:  LONGINT;  {send sequence number}
  3264.       sendWindow:  INTEGER;  {size of remote buffer}
  3265.       recvSeq:  LONGINT;  {receive sequence number}
  3266.       attnSendSeq:  LONGINT;  {attention send seq number}
  3267.       attnRecvSeq:  LONGINT;  {attention receive seq num}
  3268.       ocMode:  Byte;  {connection opening mode}
  3269.       ocInterval:  Byte;  {interval bet open requests}
  3270.      ocMaximum:Byte;{retries of open conn req}
  3271.      );
  3272.  
  3273. dspClose,
  3274. dspRemove:
  3275.     (
  3276.       abort:  Byte;  {abort send requests}
  3277.     );
  3278.  
  3279. dspStatus:
  3280.     (
  3281.       statusCCB:  TPCCB;  {pointer to CCB}
  3282.       sendQPending:  INTEGER;  {bytes waiting in send queue}
  3283.       sendQFree:  INTEGER;  {available send-queue buffer}
  3284.       recvQPending:  INTEGER;  {bytes in receive queue}
  3285.       recvQFree:  INTEGER;  {avail receive-queue buffer}
  3286. )
  3287.  
  3288.     dspRead,
  3289.     dspWrite:
  3290.     (
  3291.       reqCount:  INTEGER;  {requested number of bytes}
  3292.       actCount:  INTEGER;  {actual number of bytes}
  3293.       dataPtr:  Ptr;  {pointer to data buffer}
  3294.       eom:  Byte;  {1 if end of message}
  3295.       flush:  Byte;  {1 to send data now}
  3296.     )
  3297.  
  3298. dspAttention:
  3299.     (
  3300.       attnCode:  INTEGER;  {client attention code}
  3301.       attnSize:  INTEGER;  {size of attention data}
  3302.       attnData:  Ptr;  {pointer to attention data}
  3303.       attnInterval:  Byte;  {reserved}
  3304.     )
  3305.  
  3306. dspOptions:
  3307.     (
  3308.       sendBlocking: INTEGER;  {send-blocking threshold}
  3309.       sendTimer:    Byte;     {reserved}
  3310.       rtmtTimer:    Byte;     {reserved}
  3311.       badSeqMax:    Byte;     {retransmit advice threshold}
  3312.       useCheckSum:  Byte;     {DDP checksum for packets}
  3313.     )
  3314.  
  3315.     dspNewCID:
  3316.     (
  3317.       newCID:  INTEGER;  {new connection ID}
  3318.     )
  3319. END;
  3320.  
  3321. The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are filled
  3322. in by the Device Manager; your application should not have to set or read these
  3323. parameters. The ioResult parameter returns the result of the function; in the
  3324. case that you call the function asynchronously, the Device Manager sets this
  3325. field to 1 as soon as you call the function, and changes the field to the actual
  3326. result code when the function completes execution. The ioCompletion parameter is
  3327. a pointer to a completion routine that you can provide; the Device Manager calls
  3328. your completion routine when it completes execution of the PBControl function.
  3329. If you are not providing a completion routine, specify NIL for this field. The
  3330. ioCRefNum and csCode fields specify the driver and the command to be executed;
  3331. you must fill in the csCode field. 
  3332.  
  3333. The qStatus field is reserved for use by ADSP. The ccbRefNum field is a
  3334. reference number for the connection control block. The CCB reference number is
  3335. returned by ADSP in response to the dspInit command. You must specify this
  3336. number as a parameter to every .DSP driver routine you call subsequently.
  3337.  
  3338. The remaining parameters are used only for specific commands; each of these
  3339. parameters is described in “.DSP Driver Commands” later in this chapter.
  3340.  
  3341. _______________________________________________________________________________
  3342.  
  3343. æKY Opening…and…Maintaining…an…ADSP…Connection
  3344. æC »Opening and Maintaining an ADSP Connection                           AppleTalk Manager
  3345. _______________________________________________________________________________
  3346.  
  3347. To use ADSP to establish and maintain a connection between a socket on your
  3348. local node and a remote socket, use the following procedure:
  3349.  
  3350. 1.  Use the MPPOpen command to open the .MPP driver and then use the OpenDriver
  3351. command to open the .DSP driver. The OpenDriver routine returns the reference
  3352. number for the .DSP driver; you must supply this reference number each time you
  3353. call the .DSP driver.
  3354.  
  3355. 2.  Allocate nonrelocatable memory for a connection control block, send and
  3356. receive queues, and an attention message buffer. If you need to allocate the
  3357. memory dynamically while the program is running, use the NewPtr routine.
  3358. Otherwise, the way in which you allocate the memory depends on the compiler you
  3359. are using (the program listing at the end of this section shows how it’s done in
  3360. Pascal). The memory that you allocate becomes the property of ADSP when you call
  3361. the dspInit command to establish a connection end. You cannot write any data to
  3362. this memory except by calling ADSP, and you must ensure that the memory remains
  3363. locked until you call the dspRemove command to eliminate the connection end.
  3364.  
  3365. The connection control block is 242 bytes. The attention message buffer must be
  3366. 570 bytes. When you send bytes to a remote connection end, ADSP stores the bytes
  3367. in a buffer called the send queue. It keeps the bytes you sent in the send queue
  3368. until the remote connection end acknowledges their receipt, so that they are
  3369. available to be retransmitted if necessary. When the local connection end
  3370. receives bytes, it stores them in a buffer called the receive queue until you
  3371. read them. The sizes you need for the send and receive queues depend on the
  3372. lengths of the messages being sent. 
  3373.  
  3374. ADSP does not transmit data from the remote connection end until there is room
  3375. for it in your receive queue. If your send or receive queues are too small, they
  3376. limit the speed with which you can transmit and receive data. A queue size of
  3377. 600 bytes should work well for most applications. If you are using ADSP to send
  3378. a continuous flow of data, a larger data buffer will improve performance. If
  3379. your application is sending or receiving the user’s keystrokes, a smaller buffer
  3380. should be adequate. The constant minDSPQueueSize indicates the minimum queue
  3381. size that you can use.
  3382.  
  3383. If you are using a version of the .DSP driver prior to version 1.5, you must
  3384. allocate send and receive queues that are 12% larger than the actual buffer
  3385. sizes you need, to provide some extra space for use by the .DSP driver. Version
  3386. 1.5 and later versions of the .DSP driver use a much smaller, and variable,
  3387. portion of buffer space for overhead.
  3388.  
  3389. 3.  Use the dspInit command to establish a connection end. You must provide
  3390. pointers to the connection control block, send buffer, receive buffer, and
  3391. attention message buffer. You may also provide a pointer to the user routine
  3392. that ADSP calls when your connection end receives an unsolicited connection
  3393. event. User routines are discussed in “Writing a User Routine For Connection
  3394. Events” later in this chapter.
  3395.  
  3396. If there is a specific socket that you want to use for the connection end, you
  3397. can specify the socket number in the localSocket parameter. If you want ADSP to
  3398. assign the socket for you, specify 0 for the localSocket parameter. ADSP returns
  3399. the socket number when the dspInit command completes execution.
  3400.  
  3401. 4.  If you wish to do so, you can use the NBPRegister function to add the name
  3402. and address of your connection end to the node’s names table. The NBPRegister
  3403. function is described in the AppleTalk Manager chapter of Volume II. 
  3404.  
  3405. 5.  You can use the dspOptions command to set several parameters that control
  3406. the behavior of the connection end. Because every parameter has a default value,
  3407. the use of the dspOptions command is optional. You can specify values for the
  3408. following parameters:
  3409.  
  3410.   •   The sendBlocking parameter, which sets the maximum number of bytes that
  3411.       may accumulate in the send buffer before ADSP sends a packet to the
  3412.       remote connection end. You can experiment with different values of the
  3413.       sendBlocking parameter to determine which provides the best performance;
  3414.       the default value of 16 bytes gives good performance under most
  3415.       circumstances.
  3416.  
  3417.   •   The badSeqMax parameter, which sets the maximum number of out-of-sequence
  3418.       data packets that the local connection end can receive before requesting
  3419.       the remote connection end to retransmit the missing data. Under most
  3420.       circumstances, the default value of 3 provides good performance.
  3421.  
  3422.   •   The useCheckSum parameter, which determines whether DDP should compute a
  3423.       checksum and include it in each packet that it sends to the remote
  3424.       connection end. Using checksums slows communications slightly. Normally
  3425.       ADSP and DDP perform enough error checking to ensure safe delivery of all
  3426.       data; set the useCheckSum parameter to 1 only if you feel that the
  3427.       network is highly unreliable.
  3428.  
  3429. 6.  Call the dspOpen command to open the connection. The dspOpen command has
  3430. four possible modes of operation: ocAccept, ocEstablish, ocRequest, and
  3431. ocPassive. Normally you use either the ocRequest or ocPassive mode. You must
  3432. specify one of these four modes for the ocMode parameter when you call the
  3433. dspOpen command. 
  3434.  
  3435. The ocAccept mode is used only by connection servers. The ocEstablish mode is
  3436. used by routines that determine their connection-opening parameters and
  3437. establish a connection independently of ADSP, but use ADSP to transmit and
  3438. receive data.
  3439.  
  3440. Use the ocRequest mode when you want to establish communications with a specific
  3441. socket on the internet. When you execute the dspOpen command in the ocRequest
  3442. mode, ADSP sends an open-connection request to the address you specify. 
  3443.  
  3444. If the socket to which you send the open-connection request is a connection
  3445. listener, the connection server that operates that connection listener can
  3446. choose any socket on the internet to be the connection end that responds to the
  3447. open-connection request. To restrict the socket from which you will accept a
  3448. response to your open-connection request, specify a value for the filterAddress
  3449. parameter to the dspOpen command. When your connection end receives a response
  3450. from a socket that meets the restrictions of the filterAddress parameter, it
  3451. acknowledges the response and ADSP completes the connection. 
  3452.  
  3453. To use the ocRequest mode, you must know the complete internet address of the
  3454. remote socket, and the ADSP client at that address must either be a connection
  3455. listener or have executed the dspOpen command in the ocPassive mode. You can use
  3456. the NBPLookup function to obtain a list of names of objects on the internet and
  3457. to determine the internet address of a socket when you know its name. The
  3458. NBPLookup function is described in the AppleTalk Manager chapter of Volume II.
  3459. Enhancements to the wildcard-lookup feature of NBP are discussed in “A New NBP
  3460. Wildcard Character” earlier in this chapter. 
  3461.  
  3462. Use the ocPassive mode when you expect to receive an open-connection request
  3463. from a remote socket. You can specify a value for the filterAddress parameter to
  3464. restrict the network number, node ID, or socket number from which you will
  3465. accept an open-connection request. When your connection end receives an
  3466. open-connection request that meets the restrictions of the filterAddress
  3467. parameter, it acknowledges the request and ADSP completes the connection. 
  3468.  
  3469. You can poll the state field in the connection control block to determine when
  3470. the connection end is waiting to receive an open-connection request, when the
  3471. connection end is waiting to receive an acknowledgment of an open-connection
  3472. request, and when the connection is open. The CCB is described in “The ADSP
  3473. Connection Control Block” earlier in this chapter. Alternatively, you can check
  3474. the result code for the dspOpen command when the function completes execution.
  3475. If the function returns the noErr result code, then the connection is open.
  3476.  
  3477. 7.  Use the dspRead command to read data that your connection end has received
  3478. from the remote connection end. Use the dspWrite command to send data to the
  3479. remote connection end. Use the dspAttention command to send attention messages
  3480. to the remote connection end.
  3481.  
  3482. The dspWrite command places data in the send queue. ADSP is a full-duplex,
  3483. symmetric communication protocol. You can send data at any time, and your
  3484. connection end can receive data at any time, even at the same time as you are
  3485. sending data. ADSP transmits the data in the send queue when one of the
  3486. following conditions occurs:
  3487.  
  3488.   •   You call the dspWrite command with the flush parameter set to a nonzero
  3489.       number.
  3490.  
  3491.   •   The number of bytes in the send queue equals or exceeds the blocking
  3492.       factor that you set with the dspOptions command.
  3493.  
  3494.   •   The send timer expires. The send timer sets the maximum amount of time
  3495.       that can pass before ADSP sends all unsent data in the send queue to the
  3496.       remote connection end. ADSP calculates the best value to use for this
  3497.       timer and sets it automatically.
  3498.  
  3499.   •   A connection event requires that the local connection end send an
  3500.       acknowlegment packet to the remote connection end.
  3501.  
  3502. If you send more data to the send queue than it can hold, the dspWrite command
  3503. does not complete execution until it has written all the data to the send queue.
  3504. If you execute the dspWrite command asynchronously, ADSP returns control to your
  3505. program and writes the data to the send queue as quickly as it can. This
  3506. technique provides the most efficient use of the send queue by your program and
  3507. by ADSP. Because ADSP does not remove data from the send queue until that data
  3508. has not only been sent but also acknowledged by the remote connection end, using
  3509. the flush parameter to the dspWrite command does not guarantee that the send
  3510. queue is empty. You can use the dspStatus command to determine how much free
  3511. buffer space is available in the send queue. 
  3512.  
  3513. The dspRead command reads data from the receive queue into your application’s
  3514. private data buffer. ADSP does not transmit data until there is space available
  3515. in the other end’s receive queue to accept it. Because a full receive queue
  3516. slows the communication rate, you should read data from the receive queue as
  3517. often as necessary to keep sufficient buffer space available for new data. You
  3518. can use either of two techniques to do this:
  3519.  
  3520.   •   Allocate a small receive queue (about 600 bytes) and call the dspRead
  3521.       command asynchronously. Your completion routine for the dspRead command
  3522.       should then call the dspRead command again.
  3523.  
  3524.   •   Allocate a large receive queue and call the dspRead command less
  3525.       frequently.
  3526.  
  3527. If there is less data in the receive queue than the amount you specify with the
  3528. reqCount parameter to the dspRead command, the command does not complete
  3529. execution until there is enough data available to satisfy the request. There are
  3530. three exceptions to this rule: If the end-of-message bit in the ADSP packet
  3531. header is set, the dspRead command reads the data in the receive queue, returns
  3532. the actual amount of data read in the actCount parameter, and returns the eom
  3533. parameter set to 1. If you have closed the connection end before calling the
  3534. dspRead command (that is, the connection is half open), the command reads
  3535. whatever data is available and returns the actual amount of data read in the
  3536. actCount parameter. If ADSP has closed the connection before you call the
  3537. dspRead command , the function returns the noErr result code with the actCount
  3538. parameter set to 0 and the eom parameter set to 0.
  3539.  
  3540. In addition to the byte stream data format implemented by the dspRead and
  3541. dspWrite commands, ADSP provides a mechanism for sending and receiving control
  3542. signals or information separate from the byte stream. You use the dspAttention
  3543. command to send an attention code and an attention message to the remote
  3544. connection end. When your connection end receives an attention message, ADSP’s
  3545. interrupt handler sets the eAttention flag in the userFlags field of the
  3546. connection control block and calls your user routine. Your user routine must
  3547. clear the userFlags field, and can then read the attention code and attention
  3548. message and take whatever action you deem appropriate. 
  3549.  
  3550. Because ADSP is often used by terminal emulation programs and other applications
  3551. that pass the data they receive on to the user without processing it, attention
  3552. messages provide a mechanism for the applications that are clients of the
  3553. connection ends to communicate with each other. For example, you could use
  3554. attention messages to implement a handshaking and data checking protocol for a
  3555. program that transfers disk files between two applications, neither one of which
  3556. is a file server. Or a database server on a mainframe computer that uses ADSP to
  3557. communicate with Macintosh computer workstations could use the attention
  3558. mechanism to inform the workstations when the database is about to be closed
  3559. down for maintenance.
  3560.  
  3561. 8.  When you are ready to close the ADSP connection, you can use the dspClose or
  3562. dspRemove commands to close the connection end. Use the dspClose command if you
  3563. intend to open another connection using that connection end, and do not want to
  3564. release the memory you allocated for the connection end. Use the dspRemove
  3565. command if you are completely finished with the connection end and want to
  3566. release the memory.
  3567.  
  3568. You can continue to read data from the receive queue after you have called the
  3569. dspClose command, but not after you have called the dspRemove command. You can
  3570. use the dspStatus command to determine whether there is any data remaining in
  3571. the receive queue, or you can read data from the receive queue until both the
  3572. actCount and eom fields of the dspRead parameter block return 0.
  3573.  
  3574. If you set the abort parameter for the dspClose or dspRemove commands to 0, then
  3575. ADSP does not close the connection or the connection end until it has sent—and
  3576. received acknowledgment for—all data in the send queue and any pending attention
  3577. messages. If you set the abort parameter to 1, then ADSP discards any data in
  3578. the send queue and any attention messages that have not already been sent.
  3579.  
  3580. After you have executed the dspRemove command, you can release the memory you
  3581. allocated for the connection control block and data buffers.
  3582.  
  3583. Listing 29-2 illustrates the use of ADSP. It opens the .MPP and .DSP drivers,
  3584. and allocates memory for its internal data buffers, for the CCB, and for the
  3585. send, receive, and attention message buffers. Then it uses the dspInit command
  3586. to establish a connection end, and uses NBP to register the name of the
  3587. connection end on the internet. The routine uses the dspOptions command to set
  3588. the blocking factor to 24 bytes. Next, it uses NBP to determine the address of a
  3589. socket whose name was chosen by the user and sends an open-connection request 
  3590. (dspOpen) to that socket. When the dspOpen command completes execution, the
  3591. routine sends data and an attention message to the remote connection end, and
  3592. reads data from its receive buffer. Finally, the routine closes the connection
  3593. end with the dspRemove command and releases the memory it allocated.
  3594.  
  3595. Listing 29-2.  Using ADSP to establish and use a connection (TO BE PROVIDED)
  3596.  
  3597. _______________________________________________________________________________
  3598.  
  3599. æKY Creating…and…Using…a…Connection…Listener
  3600. æC »Creating and Using a Connection Listener                             AppleTalk Manager
  3601. _______________________________________________________________________________
  3602.  
  3603. A connection listener is a special sort of ADSP connection end that cannot
  3604. receive or transmit data streams or attention messages. The sole function of a
  3605. connection listener is to wait passively to receive an open-connection request
  3606. and to inform its client, the connection server, when it receives one. The
  3607. connection server can then accept or deny the open-connection request. If it
  3608. accepts the request, the connection server selects a socket to use as a
  3609. connection end, establishes a connection end on that socket, and sends an
  3610. acknowledgement and connection request back to the requesting connection end.
  3611. The connection server can use the same socket as it used for the connection
  3612. listener, or can select a different socket as the connection end.
  3613.  
  3614. Use the following procedure to establish a connection listener and to use that
  3615. connection listener to open a connection with a remote connection end:
  3616.  
  3617. 1.  Use the MPPOpen command to open the .MPP driver and then use the OpenDriver
  3618. command to open the .DSP driver. The OpenDriver routine returns the reference
  3619. number for the .DSP driver; you must supply this reference number each time you
  3620. call the .DSP driver.
  3621.  
  3622. 2.  Allocate nonrelocatable memory for a connection control block. A connection
  3623. listener does not need send and receive buffers or an attention message buffer.
  3624. The memory that you allocate becomes the property of ADSP when you call the
  3625. dspCLInit command to establish a connection listener. You cannot write any data
  3626. to this memory except through calls to ADSP, and you must ensure that the memory
  3627. remains locked until you call the dspRemove command to eliminate the connection
  3628. end. The connection control block is 242 bytes in size. 
  3629.  
  3630. 3.  Call the dspCLInit command to establish a connection listener. You must
  3631. provide a pointer to the connection control block.
  3632.  
  3633. If there is a specific socket that you want to use for the connection listener,
  3634. you can specify the socket number in the localSocket parameter. If you want ADSP
  3635. to assign the socket for you, specify 0 for the localSocket parameter, and ADSP
  3636. returns the socket number when the dspCLInit command completes execution.
  3637.  
  3638. 4.  If you wish, you can use the NBPRegister function to add the name and
  3639. address of your connection listener to the node’s names table. The NBPRegister
  3640. function is described in the AppleTalk Manager chapter of Volume II.
  3641.  
  3642. 5.  Use the dspCLListen command to cause the connection listener to wait for an
  3643. open-connection request. Because the dspCLListen command does not complete
  3644. execution until it receives a connection request, you should call this function
  3645. asynchronously. You can specify a value for the filterAddress parameter to
  3646. restrict the network number, node ID, or socket number from which you will
  3647. accept an open-connection request. 
  3648.  
  3649. When the dspCLListen command receives an open-connection request that meets the
  3650. restrictions of the filterAddress parameter, it returns a noErr result code (if
  3651. you executed the function asynchronously, it places a noErr result code in the
  3652. ioResult parameter) and places values in the parameter block for the remoteCID,
  3653. remoteAddress, sendSeq, sendWindow, and attnSendSeq parameters. 
  3654.  
  3655. 6.  If you want to open the connection, use the dspInit command to establish a
  3656. connection end. You can use any available socket on the node for the connection
  3657. end, including the socket that you used for the connection listener. Because a
  3658. single socket can have more than one CCB connected with it, the socket can
  3659. function simultaneously as a connection end and a connection listener. 
  3660.  
  3661. You can check the address of the remote socket to determine if it meets your
  3662. criteria for a connection end. Although the filterAddress parameter to the
  3663. dspCLListen command provides some screening of socket addresses, it cannot check
  3664. for network number ranges, for example, or for a specific set of socket numbers.
  3665. If for some reason you want to deny the connection request, call the DSPDeny
  3666. function, specifying the connection control block of the connection listener in
  3667. the ccbRefNum parameter. Because the dspCLListen command completes execution
  3668. when it receives an open-connection request, you must return to step 5 to wait
  3669. for another connection request.
  3670.  
  3671. 7.  Call the dspOpen command, specifying ocAccept for the ocMode parameter and
  3672. specifying in the ccbRefNum parameter the reference number of the connection end
  3673. that you want to use. When you call the dspOpen command , you must provide the
  3674. values returned by the dspCLListen command for the remoteCID, remoteAddress,
  3675. sendSeq, sendWindow, and attnSendSeq parameters.
  3676.  
  3677. You can poll the state field in the connection control block to determine when
  3678. the connection is open. The CCB is described in “The ADSP Connection Control
  3679. Block” earlier in this chapter. Alternatively, you can check the result code for
  3680. the dspOpen command when the function completes execution. If the function
  3681. returns the noErr result code, then the connection is open.
  3682.  
  3683. 8.  You can now send and receive data and attention messages over the
  3684. connection, as described in the preceding section, “Opening and Maintaining an
  3685. ADSP Connection.” When you are ready to close the connection, you can use the
  3686. dspClose or dspRemove commands, which are also described in the preceding
  3687. section.
  3688.  
  3689. 9.  When you are finished using the connection listener, you can use the
  3690. dspCLRemove command to eliminate it. Once you have called the dspCLRemove
  3691. command, you can release the memory you allocated for the connection listener’s
  3692. connection control block.
  3693.  
  3694. Listing 29-3 illustrates the use of ADSP to establish and use a connection
  3695. listener. It opens the .MPP and .DSP drivers, and allocates memory for the CCB.
  3696. Then it uses the dspCLInit command to establish a connection listener, uses NBP
  3697. to register the name of the connection end on the internet, and uses the
  3698. dspCLListen command to wait for a connection request. When the routine receives
  3699. a connection request, it calls the dspOpen command to complete the connection.
  3700.  
  3701. Listing 29-3.  Using ADSP to Establish and Use a Connection Listener (TO BE
  3702. PROVIDED)
  3703.  
  3704. _______________________________________________________________________________
  3705.  
  3706. æKY Writing…a…User…Routine…For…Connection…Events
  3707. æC »Writing a User Routine For Connection Events                         AppleTalk Manager
  3708. _______________________________________________________________________________
  3709.  
  3710. When you execute the dspInit command, you can specify a pointer to a routine
  3711. that you provide (referred to as the user routine). Whenever an unsolicited
  3712. connection event occurs, ADSP sets a flag in the connection control block (CCB)
  3713. and calls the user routine. The user routine must clear the flag to acknowledge
  3714. that it has read the flag field, and can then respond to the event in any manner
  3715. you deem appropriate. The CCB flags are described in “The ADSP Connection
  3716. Control Block” earlier in this chapter. There are four types of unsolicited
  3717. connection events that set flags in the CCB, as follows:
  3718.  
  3719.   •   ADSP has been informed by the remote connection end that the remote
  3720.       connection end is about to close the connection. An appropriate reponse
  3721.       might be to store a flag indicating that the connection end is about to
  3722.       close. When your application regains control, it can then display a
  3723.       dialog box informing the user of this event and asking whether the
  3724.       application should attempt to reconnect later.
  3725.  
  3726.   •   ADSP has determined that the remote connection end is not responding, and
  3727.       so has closed the connection. Your user routine can attempt to open a new
  3728.       connection immediately. Alternatively, you can store a flag indicating
  3729.       that the connection has closed and, when your application regains
  3730.       control, it can display a dialog box asking the user whether to attempt
  3731.       to reconnect.
  3732.  
  3733.   •   ADSP has received an attention message from the remote connection end.
  3734.       Depending on what you are using the attention message mechanism for, you
  3735.       might want to read the attention code in the attnCode field of the CCB
  3736.       and the attention message pointed to by the attnPtr field of the CCB.
  3737.  
  3738.   •   ADSP has received a forward reset command from the remote client end, has
  3739.       discarded all ADSP data not yet delivered—including the data in the
  3740.       local client end’s receive queue—and has resynchronized the connection.
  3741.       Your response to this event depends on the purpose for which you are
  3742.       using the forward reset mechanism. You might want to resend the last data
  3743.       you have sent or inform the user of the event.
  3744.  
  3745. When ADSP calls your user routine, the CPU is in interrupt-processing mode and
  3746. register A1 contains a pointer to the CCB of the connection end that generated
  3747. the event. You can examine the userFlags field of the CCB to determine what
  3748. event caused the interrupt, and you can examine the state field of the CCB to
  3749. determine the current state of the connection. 
  3750.  
  3751. Because the CPU is set to interrupt-processing mode, your user routine must
  3752. preserve all registers other than A0, A1, D0, D1, and D2. Your routine must not
  3753. make any direct or indirect calls to the Memory Manager, and can’t depend on
  3754. handles to unlocked blocks being valid. If you want to use any of your
  3755. application’s global variables, you must save the contents of the A5 register
  3756. before using the variables, and you must restore the A5 register before your
  3757. routine terminates. Listing 29-4 illustrates the use of the CCB to store the
  3758. contents of the A5 register while your routine is executing.
  3759.  
  3760. If you want to execute a routine each time an unsolicited connection event
  3761. occurs but the interrupt environment is too restrictive, you can specify a NIL
  3762. pointer to the user routine and periodically poll the userFlags field of the CCB
  3763. instead.
  3764.  
  3765. To ensure that you do not lose any attention messages, you must read any
  3766. attention messages into an internal buffer before you clear the bit in the
  3767. userFlags field.
  3768.  
  3769. Listing 29-4 is an example of a user routine. When this routine is called, it
  3770. first checks the connection control block to determine the source of the
  3771. interrupt and then clears the bit in the userFlags field of the CCB. If the
  3772. routine has received an attention message, the user routine reads the message
  3773. into an internal buffer before it clears the flag bit.
  3774.  
  3775. Listing 29-4.  An ADSP user routine (TO BE PROVIDED)
  3776. _______________________________________________________________________________
  3777.  
  3778. æKY DSP…Driver…Commands
  3779. æC »DSP Driver Commands                                                  AppleTalk Manager
  3780. _______________________________________________________________________________
  3781.  
  3782. The .DSP driver implements the AppleTalk Data Stream protocol (ADSP). You send
  3783. commands to ADSP and obtain information about ADSP by executing the .DSP driver
  3784. commands described in this section.  
  3785. To use a .DSP driver command, call PBControl passing a pointer to the .DSP
  3786. parameter block as a parameter and the async parameter is a Boolean that
  3787. specifies whether the function is to execute synchronously or asynchronously.
  3788. Set the async parameter to TRUE to execute the function asynchronously.
  3789.  
  3790. The .DSP parameter block is shown in “The .DSP Parameter Block” earlier in this
  3791. chapter. The parameters used with each function are described in this section.
  3792.  
  3793. For a general discussion of the use of ADSP, see “Using ADSP” earlier in this
  3794. chapter.
  3795.  
  3796. _______________________________________________________________________________
  3797.  
  3798. æKY Establishing…and…Terminating…an…ADSP…Connection
  3799. æC »Establishing and Terminating an ADSP Connection                      AppleTalk Manager
  3800. _______________________________________________________________________________
  3801.  
  3802. You can use the functions described in this section to 
  3803.  
  3804.   •   establish a connection end
  3805.   •   open a connection
  3806.   •   assign an identification number to a connection end
  3807.   •   set the values for parameters that control the behavior of a connection
  3808.       end
  3809.   •   close a connection end
  3810.   •   eliminate a connection end
  3811.  
  3812. The parameter block for the dspInit command looks like this:
  3813.  
  3814. Parameter block
  3815.   ¨  16  ioResult  word  result code 
  3816.   Æ  26  csCode  word  always dspInit
  3817.   ¨  32  ccbRefNum  word  reference number for CCB
  3818.   Æ  34  ccbPtr  long  pointer to connection control block
  3819.   Æ  38  userRoutine  long  pointer to routine to call on 
  3820.           connection events
  3821.   Æ  42  sendQSize  word  size in bytes of the send queue
  3822.   Æ  44  sendQueue  long  pointer to send queue
  3823.   Æ  48  recvQSize  word  size in bytes of the receive queue
  3824.   Æ  50  recvQueue  long  pointer to receive queue
  3825.   Æ  54  attnPtr  long  pointer to buffer for incoming 
  3826.           attention messages
  3827.   ´  58  localSocket  byte  DDP socket number for this 
  3828.           connection end
  3829.  
  3830. The dspInit command establishes a connection end; that is, it assigns a specific
  3831. socket for use by ADSP and initializes the variables that ADSP uses to maintain
  3832. the connection. The dspInit command does not open the connection end or
  3833. establish a connection with a remote connection end; follow the dspInit command
  3834. with the dspOpen command to perform those tasks. Use the dspCLInit command to
  3835. establish a connection listener. Use the dspRemove command to eliminate a
  3836. connection end.
  3837.  
  3838. When you send bytes to a remote connection end, ADSP stores the bytes in a
  3839. buffer called the send queue. It keeps the bytes you sent in the send queue
  3840. until the remote connection end acknowledges their receipt, so that they are
  3841. available to be retransmitted if necessary. When the local connection end
  3842. receives bytes, it stores them in a buffer called the receive queue until you
  3843. read them. 
  3844.  
  3845. You must allocate memory for the send and receive queues, and for a buffer that
  3846. holds incoming attention messages. You must also allocate a nonrelocatable block
  3847. of memory for the connection control block for this connection end. 
  3848.  
  3849. Note:  When you use the dspInit command, the memory that you allocate becomes
  3850. the property of ADSP. You cannot write any data to this memory except by calling
  3851. ADSP routines, and you must ensure that the memory remains locked until you call
  3852. the dspRemove command to eliminate the connection end. 
  3853.  
  3854. Parameters
  3855.  
  3856. ioResult
  3857. The result of the function. When you execute the function asynchronously, the
  3858. function sets this parameter to 1 and returns a function result of noErr as soon
  3859. as the function begins execution. When the function completes execution, it sets
  3860. the ioResult parameter to the actual result code. 
  3861.  
  3862. csCode
  3863. The routine selector, you should set this to dspInit for this command.
  3864.  
  3865. ccbRefNum
  3866. The reference number for the connection control block. The dspInit command
  3867. returns this number. You must provide this number in all subsequent calls to
  3868. this connection end.
  3869.  
  3870. ccbPtr
  3871. A pointer to the connection control block that you allocated. The connection
  3872. control block is 242 bytes in size, and is described in “The ADSP Connection
  3873. Control Block” earlier in this chapter.
  3874.  
  3875. userRoutine
  3876. A pointer to a routine that is to be called each time the connection end
  3877. receives an unsolicited connection event. Specify NIL for this parameter if you
  3878. do not want to supply a user routine. Connection events and user routines are
  3879. discussed in “Writing a User Routine For Connection Events” earlier in this
  3880. chapter.
  3881.  
  3882. sendQSize
  3883. The size in bytes of the send queue. A queue size of 600 bytes should work well
  3884. for most applications. If you are using ADSP to send a continuous flow of data,
  3885. a larger data buffer will improve performance. If your application is sending
  3886. the user’s keystrokes, a smaller buffer should be adequate. The constant
  3887. minDSPQueueSize indicates the minimum queue size that you can use.
  3888.  
  3889.  
  3890. sendQueue
  3891. A pointer to the send queue that you allocated. 
  3892.  
  3893. recvQSize
  3894. The size in bytes of the receive queue. A queue size of 600 bytes should work
  3895. well for most applications. If you are using ADSP to receive a continuous flow
  3896. of data, a larger data buffer will improve performance. If your application is
  3897. receiving a user’s keystrokes, a smaller buffer should be adequate. The constant
  3898. minDSPQueueSize indicates the minimum queue size that you can use.
  3899.  
  3900. recvQueue
  3901. A pointer to the receive queue that you allocated.
  3902.  
  3903. attnPtr
  3904. A pointer to the attention-message buffer that you allocated. The
  3905. attention-message buffer must be the size of the constant attnBufSize.
  3906.  
  3907. localSocket
  3908. The DDP socket number of the socket that you want ADSP to use for this
  3909. connection end. Specify 0 for this parameter to cause ADSP to assign the socket.
  3910. In the latter case, ADSP returns the socket number when the dspInit command
  3911. completes execution.
  3912.  
  3913. Result codes
  3914. noErr                0  no error
  3915. ddpSktErr          –91  error opening socket
  3916. errDSPQueueSize  –1274  send or receive queue too small
  3917.  
  3918. The parameter block for the dspOptions command looks like this:
  3919.  
  3920. Parameter block
  3921.   ¨  16  ioResult  word  result code 
  3922.   Æ  26  csCode  word  always dspOptions
  3923.   Æ  32  ccbRefNum  word  reference number of connection end
  3924.   Æ  34  sendBlocking  word  send-blocking threshold
  3925.   Æ  38  badSeqMax  byte  threshold to send retransmit advice
  3926.   Æ  39  useCheckSum  byte  use DDP checksum?
  3927.  
  3928. The dspOptions command allows you to set values for several parameters that
  3929. affect the behavior of the local connection end. You can set the options for any
  3930. established connection end, whether open or not.
  3931.  
  3932. Parameters
  3933.  
  3934. ioResult
  3935. The result of the function. When you execute the function asynchronously, the
  3936. function sets this parameter to 1 and returns a function result of noErr as soon
  3937. as the function begins execution. When the function completes execution, it sets
  3938. the ioResult parameter to the actual result code. 
  3939.  
  3940. csCode
  3941. The routine selector, you should set this to dspOptions for this command.
  3942.  
  3943. ccbRefNum
  3944. The connection control block reference number that was returned by the dspInit
  3945. command.
  3946.  
  3947. sendBlocking
  3948. The maximum number of bytes that may accumulate in the send buffer before ADSP
  3949. sends a packet to the remote connection end. ADSP sends a packet before the
  3950. maximum number of bytes accumulates if the period specified by the send timer
  3951. expires, if you execute the dspWrite command with the flush parameter set to 1,
  3952. or if a connection event requires that the local connection end send an
  3953. acknowledgement packet to the remote connection end.
  3954.  
  3955. You can set the sendBlocking parameter to any value from 1 byte to the maximum
  3956. size of a packet (572 bytes). If you set the sendBlocking parameter to 0, the
  3957. current value for this parameter is not changed. The default value for the
  3958. sendBlocking parameter is 16 bytes.
  3959.  
  3960. badSeqMax
  3961. The maximum number of out-of-sequence data packets that the local connection end
  3962. can receive before requesting the remote connection end to retransmit the
  3963. missing data. Because a connection end does not acknowledge the receipt of a
  3964. data packet received out of sequence, the remote connection end’s retransmit
  3965. timer will expire eventually and it will retransmit the data. The badSeqMax
  3966. allows you to cause the data to be retransmitted before the remote connection
  3967. end’s retransmit timer has expired.
  3968.  
  3969. You can set the badSeqMax parameter to any value from 1 to 255. If you set the
  3970. badSeqMax parameter to 0, the current value for this parameter is not changed.
  3971. The default value for the badSeqMax parameter is 3.
  3972.  
  3973. useCheckSum
  3974. A flag specifying whether DDP should compute a checksum and include it in each
  3975. packet that it sends to the remote connection end. Set this parameter to 1 to
  3976. cause DDP to use checksums, or to 0 if you do not want DDP to use checksums. The
  3977. default value for useCheckSum is 0.
  3978.  
  3979. ADSP cannot include a checksum in a packet that has a short DDP header; that is,
  3980. a packet being sent over LocalTalk to a remote socket that is on the same cable
  3981. as the local socket. Note that the useCheckSum parameter affects only whether
  3982. ADSP includes a checksum in a packet that it is sending. If ADSP receives a
  3983. packet that includes a checksum, it validates the checksum regardless of the
  3984. setting of the useCheckSum parameter. 
  3985.  
  3986. Result codes
  3987. noErr          0  no error
  3988. errRefNum  –1280  bad connection reference number
  3989.  
  3990. The parameter block for the dspOpen command looks like this:
  3991.  
  3992. Parameter block
  3993.   ¨  16  ioResult  word  result code 
  3994.   Æ  26  csCode  word  always dspOpen
  3995.   Æ  32  ccbRefNum  word  reference number of connection end
  3996.   ¨  34  localCID  word  ID of this connection end
  3997.   ´  36  remoteCID  word  ID of remote connection end
  3998.   ´  38  remoteAddress  long  remote internet address
  3999.   Æ  42  filterAddress  long  filter for open connection requests
  4000.   ´  46  sendSeq  long  initial send sequence number
  4001.   ´  50  sendWindow  word  initial size of remote receive buffer
  4002.   Æ  52  recvSeq  long  initial receive sequence number
  4003.   ´  56  attnSendSeq  long  attention send sequence number
  4004.   Æ  60  attnRecvSeq  long  attention receive sequence number
  4005.   Æ  64  ocMode  byte  connection opening mode
  4006.   Æ  65  ocInterval  byte  interval between open requests
  4007.   Æ  66  ocMaximum  byte  retries of open connection request
  4008.  
  4009. You use the ocMode field of the parameter block to specify the opening mode that
  4010. the dspOpen command is to use. The dspOpen command puts a connection end into
  4011. one of four possible opening modes, as follows: 
  4012.  
  4013.   •   The ocRequest mode, in which ADSP attempts to open a connection with the
  4014.       socket at the internet address you specify with the remoteAddress
  4015.       parameter. If the socket you specify as a remote address is a connection
  4016.       listener, it is possible that your application will receive a connection
  4017.       acknowledgement and request from a different address than the one to
  4018.       which you sent the open-connection request. You can use the filterAddress
  4019.       parameter to restrict the addresses with which you will accept a
  4020.       connection.
  4021.  
  4022. The dspOpen command completes execution in the ocRequest mode when either ADSP
  4023. establishes a connection, your connection end receives a connection denial from
  4024. the remote connection end, your connection end denies the connection request
  4025. returned by a connection listener, or ADSP cannot complete the connection (ADSP
  4026. has exceeded the maximum number of retries that you specified with the ocMaximum
  4027. parameter).
  4028.  
  4029.   •   The ocPassive mode, in which the connection end waits to receive an
  4030.       open-connection request from a remote connection end. You can use the
  4031.       filterAddress parameter to restrict the addresses from which you will
  4032.       accept a connection request.
  4033.  
  4034. The dspOpen command completes execution in the ocPassive mode when ADSP
  4035. establishes a connection or when either connection end receives a connection
  4036. denial.
  4037.  
  4038.   •   The ocAccept mode, used by connection servers to complete an
  4039.       open-connection dialog. When a connection server is informed by its
  4040.       connection listener that the connection listener has received an
  4041.       open-connection request, the connection server uses the dspInit command
  4042.       to establish a connection end and then calls the dspOpen command in
  4043.       ocAccept mode to complete the connection. You must obtain the following
  4044.       parameters from the dspCLListen command and provide them to the dspOpen
  4045.       command: remoteAddress, remoteCID, sendSeq, sendWindow, and attnSendSeq.
  4046.       Connection listeners and connection servers are described in “Creating
  4047.       and Using a Connection Listener,” earlier in this chapter, and in
  4048.       “Establishing and Terminating an ADSP Connection Listener,” later in this
  4049.       chapter.
  4050.  
  4051. The dspOpen command completes execution in the ocAccept mode when ADSP
  4052. establishes a connection or when either connection end receives a connection
  4053. denial.
  4054.  
  4055.   •   The ocEstablish mode, in which ADSP considers the connection end
  4056.       established and the connection state open. This mode is for use by
  4057.       clients that determine their connection-opening parameters without using
  4058.       ADSP or the .DSP driver to do so.
  4059.  
  4060. You must first use the dspInit command to establish a connection end and then
  4061. execute the dspNewCID command to obtain an identification number for the local
  4062. connection end. You must then communicate with the remote connection end to send
  4063. it the local connection ID and to determine the values of the following
  4064. parameters: remoteAddress, remoteCID, sendSeq, sendWindow, recvSeq, attnSendSeq,
  4065. and attnRecvSeq. Only then can you execute the dspOpen command in the
  4066. ocEstablish mode.
  4067.  
  4068. The dspOpen command completes execution in the ocEstablish mode immediately. 
  4069. The use of parameters by the dspOpen command depends on the mode in which the
  4070. function is executed, as follows:
  4071.  
  4072. ocRequest         ocPassive         ocAccept          ocEstablish
  4073.  
  4074. ¨ ioResult        ¨ ioResult        ¨ ioResult        ¨ ioResult
  4075. Æ csCode          Æ csCode          Æ csCode          Æ csCode
  4076. Æ ccbRefNum       Æ ccbRefNum       Æ ccbRefNum       Æ ccbRefNum
  4077. ¨ localCID        ¨ localCID        ¨ localCID        — localCID
  4078. ¨ remoteCID       ¨ remoteCID       Æ remoteCID       Æ remoteCID
  4079. Æ remoteAddress   ¨ remoteAddress   Æ remoteAddress   Æ remoteAddress
  4080. Æ filterAddress   Æ filterAddress   — filterAddress   — filterAddress
  4081. ¨ sendSeq         ¨ sendSeq         Æ sendSeq         Æ sendSeq
  4082. ¨ sendWindow      ¨ sendWindow      Æ sendWindow      Æ sendWindow
  4083. — recvSeq         — recvSeq         — recvSeq         Æ recvSeq
  4084. ¨ attnSendSeq     ¨ attnSendSeq     Æ attnSendSeq     Æ attnSendSeq
  4085. — attnRecvSeq     — attnRecvSeq     — attnRecvSeq     Æ attnRecvSeq
  4086. Æ ocMode          Æ ocMode          Æ ocMode          Æ ocMode
  4087. Æ ocInterval      Æ ocInterval      Æ ocInterval      — ocInterval
  4088. Æ ocMaximum       Æ ocMaximum       Æ ocMaximum       — ocMaximum
  4089.  
  4090. Parameters
  4091.  
  4092. ioResult
  4093. The result of the function. When you execute the function asynchronously, the
  4094. function sets this parameter to 1 and returns a function result of noErr as soon
  4095. as the function begins execution. When the function completes execution, it sets
  4096. the ioResult parameter to the actual result code. 
  4097. csCode  The routine selector, you should set this to dspOpen for this command.
  4098.  
  4099. ccbRefNum
  4100. The connection control block reference number that was returned by the dspInit
  4101. command for the connection end that you want to use.
  4102.  
  4103. localCID
  4104. The identification number of the local connection end. This number is assigned
  4105. by ADSP when the connection is opened. ADSP includes this number in every packet
  4106. sent to a remote connection end. Before you call the dspOpen command in
  4107. ocEstablish mode, you must call the dspNewCID command to cause ADSP to assign
  4108. this value.
  4109.  
  4110. remoteCID
  4111. The identification number of the remote connection end. This parameter is
  4112. returned by the dspOpen command in the ocRequest and ocPassive modes. A
  4113. connection server must provide this number to the dspOpen command when the
  4114. server executes the function in ocAccept mode; in this case, the connection
  4115. server obtains the remoteCID value from the dspCLListen command. You must
  4116. provide the remoteCID value to the dspOpen command when you use the function in
  4117. ocEstablish mode. 
  4118.  
  4119. remoteAddress
  4120. The internet address of the remote socket with which you wish to establish
  4121. communications, consisting of a 2-byte network number, a 1-byte node ID, and a
  4122. 1-byte socket number. You must provide this parameter when you call the dspOpen
  4123. command in the ocRequest or ocEstablish modes. This parameter is returned by the
  4124. dspOpen command when you call the function in the ocPassive mode. When you call
  4125. the dspOpen command in the ocAccept mode, you must use the value for the
  4126. remoteAddress parameter that was returned by the dspCLListen command. 
  4127. filterAddress  The internet address of the socket from which you will accept a
  4128. connection request. The address consists of three fields, a 2-byte network
  4129. number, a 1-byte node ID, and a 1-byte socket number. Specify 0 for any of these
  4130. fields for which you wish to impose no restrictions. If you specify a filter
  4131. address of $00082500, for example, the connection end will accept a connection
  4132. request from any socket at node $25 of network $0008. Set the filterAddress
  4133. parameter equal to the remoteAddress parameter to accept a connection only with
  4134. the socket to which you sent a connection request.
  4135.  
  4136. When you execute the dspOpen command in the ocPassive mode, you can receive a
  4137. connection request from any ADSP connection end on the internet. When you
  4138. execute the dspOpen command in the ocRequest mode, your connection end can
  4139. receive a connection request acknowledgment from an address different from the
  4140. one you specified in the remoteAddress parameter only if the remote address you
  4141. specified was that of a connection listener. in either case, you can use the
  4142. filterAddress parameter to avoid acknowledging unwanted connection requests. 
  4143.  
  4144. When you execute the dspOpen command in the ocAccept mode, your connection
  4145. listener has already received and decided to accept the connection request. You
  4146. can specify a filter address for a connection listener with the dspCLListen
  4147. command. A connection server can use the dspCLDeny command to deny a connection
  4148. request that was accepted by its connection listener.
  4149.  
  4150. You cannot use the filter address when you execute the dspOpen command in
  4151. ocEstablish mode.
  4152.  
  4153. sendSeq
  4154. The sequence number of the first byte that the local connection end will send to
  4155. the remote connection end. ADSP uses this number to coordinate communications
  4156. and for error checking. ADSP returns a value for the sendSeq parameter when you
  4157. execute the dspOpen command in the ocRequest or ocPassive modes. When you
  4158. execute the dspOpen command in the ocAccept mode, you must specify the value for
  4159. the sendSeq parameter that was returned by the dspCLListen command. You must
  4160. provide the value for this parameter when you execute the dspOpen command in the
  4161. ocEstablish mode.
  4162.  
  4163. sendWindow
  4164. The sequence number of the last byte that the remote connection end has buffer
  4165. space to receive. ADSP uses this number to coordinate communications and for
  4166. error checking. ADSP returns a value for the sendWindow parameter when you
  4167. execute the dspOpen command in the ocRequest or ocPassive modes. When you
  4168. execute the dspOpen command in the ocAccept mode, you must specify the value for
  4169. the sendWindow parameter that was returned by the dspCLListen command. You must
  4170. provide the value for this parameter when you execute the dspOpen command in the
  4171. ocEstablish mode.
  4172.  
  4173. recvSeq
  4174. The sequence number of the next byte that the local connection end expects to
  4175. receive. ADSP uses this number to coordinate communications and for error
  4176. checking. You must provide the value for this parameter when you execute the
  4177. dspOpen command in the ocEstablish mode. The dspOpen command does not use this
  4178. parameter when you execute it in any other mode.
  4179.  
  4180. attnSendSeq
  4181. The sequence number of the next attention packet that the local connection end
  4182. will transmit. ADSP uses this number to coordinate communications and for error
  4183. checking. ADSP returns a value for the attnSendSeq parameter when you execute
  4184. the dspOpen command in the ocRequest or ocPassive modes. When you execute the
  4185. dspOpen command in the ocAccept mode, you must specify the value for the
  4186. attnSendSeq parameter that was returned by the dspCLListen command. You must
  4187. provide the value for this parameter when you execute the dspOpen command in the
  4188. ocEstablish mode.
  4189.  
  4190. attnRecvSeq
  4191. The sequence number of the next attention packet that the local connection end
  4192. expects to receive. ADSP uses this number to coordinate communications and for
  4193. error checking. You must provide the value for this parameter when you execute
  4194. the dspOpen command in the ocEstablish mode. The dspOpen command does not use
  4195. this parameter when you execute it in any other mode.
  4196.  
  4197. ocMode
  4198. The mode in which the dspOpen command is to operate, as follows: 
  4199.  
  4200. Mode         Value  Meaning
  4201. ocRequest    1      ADSP attempts to open a connection with the socket you
  4202. specify
  4203. ocPassive    2      The connection end waits to receive a connection request
  4204. ocAccept     3      The connection server accepts and acknowledges receipt of a
  4205. connection request
  4206. ocEstablish  4   ADSP considers the connection established and open; you are
  4207. responsible for setting up and synchronizing both connection ends
  4208.  
  4209. ocInterval
  4210. The period between transmissions of open-connection requests. If the remote
  4211. connection end does not acknowledge or deny an open-connection request, ADSP
  4212. retransmits the request after a time period specified by this parameter. The
  4213. time period used by ADSP is (ocInterval ¥ 10) ticks; or (ocInterval /
  4214. 6) seconds. For example, if you set the ocInterval parameter to 3, the time
  4215. period between retransmissions is 30 ticks (1/2 second). You can set the
  4216. ocInterval parameter to any value from 1 (1/6 second) to 180 (30 seconds). If
  4217. you specify 0 for the ocInterval parameter, ADSP uses the default value of 6 (1
  4218.  
  4219.  
  4220. You must provide a value for the ocInterval parameter when you execute the
  4221. dspOpen command in the ocRequest, ocPassive, or ocAccept modes. The dspOpen
  4222. command does not use this parameter when you execute it in the ocEstablish mode.
  4223.  
  4224. ocMaximum
  4225. The maximum number of times to retransmit an open-connection request before ADSP
  4226. terminates execution of the dspOpen command. If you specify 0 for the ocMaximum
  4227. parameter, ADSP uses the default value of 3. If you specify 255 for the
  4228. ocMaximum parameter, ADSP retransmits the open-connection request indefinitely
  4229. until the remote connection end either acknowledges or denies the request.
  4230.  
  4231. You must provide a value for the ocMaximum parameter when you execute the
  4232. dspOpen command in the ocRequest, ocPassive, or ocAccept modes. The dspOpen
  4233. command does not use this parameter when you execute it in the ocEstablish mode.
  4234.  
  4235. Result codes
  4236. noErr           0  no error
  4237. errOpening  –1277  attempt to open connection failed
  4238. errState    –1278  connection end must be closed
  4239. errAborted  –1279  request aborted by dspRemove or dspClose command
  4240. errRefNum   –1280  bad connection reference number
  4241.  
  4242. The parameter block for the dspNewCID command looks like this:
  4243.  
  4244. Parameter block
  4245.   ¨  16  ioResult  word  result code 
  4246.   Æ  26  csCode  word  always dspNewCID
  4247.   Æ  32  ccbRefNum  word  reference number of connection end
  4248.   ¨  34  newCID  word  ID of new connection
  4249.  
  4250. The dspNewCID command causes ADSP to assign an identification number to a
  4251. connection end without opening the connection end or attempting to establish a
  4252. connection with a remote connection end. Use this function only if you implement
  4253. your own protocol to establish communications with a remote connection end. You
  4254. must first use the dspInit command to establish a connection end. Next, you must
  4255. call the dspNewCID command to obtain a connection-end ID. Then you must
  4256. establish communication with a remote connection end and pass the ID to the
  4257. remote connection end. Finally, you must call the dspOpen command in ocEstablish
  4258. mode to cause ADSP to open the connection. See the description of the dspOpen
  4259. command for more information on establishing a connection in this fashion.
  4260.  
  4261. The ioResult parameter returns the result of the function; in the case that you
  4262. call the function asynchronously, the function sets this field to 1 as soon as
  4263. it begins execution, and changes the field to the actual result code when it
  4264. completes execution. The csCode parameter is the routine selector; you should
  4265. set this to dspNewCID for this command. The ccBRefNum parameter is the
  4266. connection control block reference number that was returned by the dspInit
  4267. command. The newCID parameter is the connection-end identification number
  4268. returned by this function. You must provide this number to the client of the
  4269. remote connection end so that it can use it for the remoteCID parameter when it
  4270. calls the dspOpen command.
  4271.  
  4272. Result codes
  4273. noErr          0  no error
  4274. errState   –1278  connection is not closed
  4275. errRefNum  –1280  bad connection reference number
  4276.  
  4277. The parameter block for the dspClose command looks like this:
  4278.  
  4279. Parameter block
  4280.   ¨  16  ioResult  word  result code 
  4281.   Æ  26  csCode  word  always dspClose
  4282.   Æ  32  ccbRefNum  word  reference number of connection end
  4283.   Æ  34  abort  byte  abort send requests if not 0
  4284.  
  4285. The dspClose command closes the connection end. The connection end is still
  4286. established; that is, ADSP retains ownership of the connection control block,
  4287. send queue, receive queue, and attention-message buffer. You can continue to
  4288. read bytes from the receive queue after you have called the dspClose command.
  4289. Use the dspRemove command instead of the dspClose command if you are through
  4290. reading bytes from the receive queue and want to release the memory associated
  4291. with the connection end. The dspClose command does not return an error if you
  4292. call it for a connection end that is already closed.
  4293.  
  4294. The ioResult parameter returns the result of the function; in the case that you
  4295. call the function asynchronously, the function sets this field to 1 as soon as
  4296. it begins execution, and changes the field to the actual result code when it
  4297. completes execution. The csCode parameter is the routine selector; you should
  4298. set this to dspClose for this command. The ccBRefNum parameter is the connection
  4299. control block reference number that was returned by the dspInit command. If the
  4300. abort parameter is nonzero, ADSP cancels any outstanding requests to send data
  4301. packets (such as the dspAttention command) and discards all data in the send
  4302. queue. If the abort parameter is 0, ADSP does not close the connection end until
  4303. all of the data in the send queue and all outstanding attention messages have
  4304. been sent and acknowledged.
  4305.  
  4306. Result codes
  4307. noErr          0  no error
  4308. errRefNum  –1280  bad connection reference number
  4309.  
  4310. The parameter block for the dspRemove command looks like this:
  4311.  
  4312. Parameter block
  4313.   ¨  16  ioResult  word  result code 
  4314.   Æ  26  csCode  word  always dspRemove
  4315.   Æ  32  ccbRefNum  word  reference number of connection end
  4316.   Æ  34  abort  byte  abort connection if not 0
  4317.  
  4318. The dspRemove command closes any open connection and eliminates the connection
  4319. end; that is, ADSP no longer retains control of the connection control block,
  4320. send queue, receive queue, and attention-message buffer. You cannot continue to
  4321. read bytes from the receive queue after you have called the dspRemove command.
  4322. After you call the dspRemove command, you can release all of the memory you
  4323. allocated for the connection end if you do not intend to reopen the connection
  4324. end.
  4325.  
  4326. The ioResult parameter returns the result of the function; in the case that you
  4327. call the function asynchronously, the function sets this field to 1 as soon as
  4328. it begins execution, and changes the field to the actual result code when it
  4329. completes execution. The csCode parameter is the routine selector; you should
  4330. set this to dspRemove for this command. The ccbRefNum parameter is the
  4331. connection control block reference number that was returned by the dspInit
  4332. command. If the abort parameter is nonzero, ADSP cancels any outstanding
  4333. requests to send data packets (such as the dspAttention command) and discards
  4334. all data in the send queue. If the abort parameter is 0, ADSP does not close the
  4335. connection end until all of the data in the send queue has been sent and
  4336. acknowledged.
  4337.  
  4338. Result codes
  4339. noErr          0  no error
  4340. errRefNum  –1280  bad connection reference number
  4341. _______________________________________________________________________________
  4342.  
  4343. æKY Establishing…and…Terminating…an…ADSP…Connection…Listener
  4344. æC »Establishing and Terminating an ADSP Connection Listener             AppleTalk Manager
  4345. _______________________________________________________________________________
  4346.  
  4347. A connection listener is a special kind of connection end that listens for
  4348. open-connection requests from remote connection ends. Connection listeners are
  4349. used by connection servers; that is, programs that assign a socket for the local
  4350. connection end only after they receive a connection request from a remote
  4351. connection end. A single connection listener, then, can receive connection
  4352. requests from any number of remote connection ends. 
  4353.  
  4354. You can use the functions in this section to
  4355.  
  4356.   •   establish a connection listener
  4357.   •   cause the connection listener to wait for a connection request
  4358.   •   deny a connection request
  4359.   •   close and eliminate a connection listener
  4360.  
  4361. The parameter block for the dspCLInit command looks like this:
  4362.  
  4363. Parameter block
  4364.   ¨  16  ioResult  word  result code 
  4365.   Æ  26  csCode  word  always dspCLInit
  4366.   ¨  32  ccbRefNum  word  reference number of connection end
  4367.   Æ  34  ccbPtr  long  pointer to CCB
  4368.   ´  58  localSocket  byte  local DDP socket number
  4369.  
  4370. The dspCLInit command establishes a connection listener; that is, it assigns a
  4371. specific socket for use by ADSP and initializes the variables that ADSP uses to
  4372. maintain a connection listener. The dspCLInit command does not cause the
  4373. connection listener to listen for connection requests; follow the dspCLInit
  4374. command with the dspCLListen command to activate the connection listener. Use
  4375. the dspInit command to establish a connection end that is not a connection
  4376. listener. Use the dspCLRemove command to eliminate a connection listener.
  4377.  
  4378. The ioResult parameter returns the result of the function; in the case that you
  4379. call the function asynchronously, the function sets this field to 1 as soon as
  4380. it begins execution, and changes the field to the actual result code when it
  4381. completes execution. The csCode parameter is the routine selector; you should
  4382. set this to dspCLInit for this command.The dspCLInit command returns the
  4383. ccbRefNum parameter, which is the reference number for the connection control
  4384. block. You must provide this number in all subsequent dspCLListen and
  4385. dspCLRemove calls to this connection listener. 
  4386. You must allocate memory for a connection control block before you call the
  4387. dspCLInit command. The ccbPtr parameter is a pointer to the connection control
  4388. block that you allocated. The connection control block is 242 bytes, and is
  4389. described in “The ADSP Connection Control Block” earlier in this chapter.
  4390.  
  4391. The localSocket parameter is the DDP socket number of the socket that you want
  4392. ADSP to use for this connection end. Specify 0 for this parameter to cause ADSP
  4393. to assign the socket. In the latter case, ADSP returns the socket number when
  4394. the dspCLInit command completes execution.
  4395.  
  4396. Result codes
  4397. noErr        0  no error
  4398. ddpSktErr  –91  error opening socket
  4399.  
  4400. The parameter block for the dspCLListen command looks like this:
  4401.  
  4402. Parameter block
  4403.   ¨  16  ioResult  word  result code 
  4404.   Æ  26  csCode  word  always dspCLListen
  4405.   Æ  32  ccbRefNum  word  reference number of connection end
  4406.   ¨  36  remoteCID  word  ID of remote connection end
  4407.   ¨  38  remoteAddress  long  remote internet address
  4408.   Æ  42  filterAddress  long  filter for open connection requests
  4409.   ¨  46  sendSeq  long  initial send sequence number
  4410.   ¨  50  sendWindow  word  initial size of remote receive buffer
  4411.   ¨  56  attnSendSeq  long  attention send sequence number
  4412.  
  4413. The dspCLListen command causes a connection listener to listen for connection
  4414. requests. You must have already used the dspCLInit command to establish a
  4415. connection listener before using the dspCLListen command. The dspCLListen
  4416. command is used only by connection servers.
  4417.  
  4418. When ADSP receives an open-connection request from a socket that satisfies the
  4419. address requirements of the filterAddress parameter, it returns values for the
  4420. remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq parameters and
  4421. completes execution of the dspCLListen command. You must then either accept the
  4422. open-connection request by calling the dspOpen command in the ocAccept mode or
  4423. deny the request by calling the dspCLDeny command.
  4424.  
  4425. You can call the dspCLListen command several times, specifying the same
  4426. connection listener. For example, if you wanted to accept connections from any
  4427. or all of three different addresses, you could call the dspCLListen command
  4428. three times with a different value for the filterAddress parameter each time.
  4429. Note that you must execute the dspCLListen command asynchronously to take
  4430. advantage of this feature.
  4431.  
  4432. Parameters
  4433.  
  4434. ioResult
  4435. The result of the function. When you execute the function asynchronously, the
  4436. function sets this parameter to 1 and returns a function result of noErr as soon
  4437. as the function begins execution. When the function completes execution, it sets
  4438. the ioResult parameter to the actual result code.
  4439.  
  4440. csCode
  4441. The routine selector; you should set this to dspCLListen for this command.
  4442.  
  4443. ccbRefNum
  4444. The connection control block reference number that was returned by the dspCLInit
  4445. command.
  4446.  
  4447. remoteCID
  4448. The identification number of the remote connection end. You must pass this value
  4449. to the dspOpen command when you open the connection or to the dspCLDeny command
  4450. when you deny the connection request.
  4451.  
  4452. remoteAddress
  4453. The internet address of the remote socket that sent a request to open a
  4454. connection. This address consists of a 2-byte network number, a 1-byte node ID,
  4455. and a 1-byte socket number. You must pass this value to the dspOpen command when
  4456. you open the connection or to the dspCLDeny command when you deny the connection
  4457. request.
  4458.  
  4459. filterAddress
  4460. The internet address of the socket from which you will accept a connection
  4461. request. The address consists of three fields, a 2-byte network number, a 1-byte
  4462. node ID, and a 1-byte socket number. Specify 0 for any of these fields for which
  4463. you wish to impose no restrictions. If you specify a filter address of
  4464. $00082500, for example, the connection listener will accept a connection request
  4465. from any socket at node $25 of network $0008. 
  4466.  
  4467. sendSeq
  4468. The sequence number of the first byte that the local connection end will send to
  4469. the remote connection end. ADSP uses this number to coordinate communications
  4470. and for error checking. You must pass this value to the dspOpen command when you
  4471. open the connection.
  4472.  
  4473. sendWindow
  4474. The sequence number of the last byte that the remote connection end has buffer
  4475. space to receive. ADSP uses this number to coordinate communications and for
  4476. error checking. You must pass this value to the dspOpen command when you open
  4477. the connection.
  4478.  
  4479. attnSendSeq
  4480. The sequence number of the next attention packet that the local connection end
  4481. will transmit. ADSP uses this number to coordinate communications and for error
  4482. checking. You must pass this value to the dspOpen command when you open the
  4483. connection.
  4484.  
  4485. Result codes
  4486. noErr           0  no error
  4487. errState    –1278  not a connection listener
  4488. errAborted  –1279  request aborted by the dspRemove command
  4489. errRefNum   –1280  bad connection reference number
  4490.  
  4491. The parameter block for the dspCLDeny command looks like this:
  4492.  
  4493. Parameter block
  4494.   ¨  16  ioResult  word  result code 
  4495.   Æ  26  csCode  word  always dspCLDeny
  4496.   Æ  32  ccbRefNum  word  reference number of connection 
  4497.           listener
  4498.   Æ  36  remoteCID  word  ID of remote connection end
  4499.   Æ  38  remoteAddress  long  remote internet address
  4500.  
  4501. The dspCLDeny command is used by a connection server to inform a remote
  4502. connection end that its request to open a connection cannot be honored.
  4503.  
  4504. The ioResult parameter returns the result of the function; in the case that you
  4505. call the function asynchronously, the function sets this field to 1 as soon as
  4506. it begins execution, and changes the field to the actual result code when it
  4507. completes execution. The csCode parameter is the routine selector; you should
  4508. set this to dspCLDeny for this command. The ccbRefNum parameter is the reference
  4509. number for the connection listener that received the connection request. This
  4510. number is returned by the dspCLInit command when you establish a connection
  4511. listener. The remoteCID and remoteAddress parameters specify the address and ID
  4512. of the remote connection end. These parameters are returned by the dspCLListen
  4513. command.
  4514.  
  4515. Result codes
  4516. noErr           0  no error
  4517. errState    –1278  not a connection listener
  4518. errAborted  –1279  request aborted by the dspRemove command
  4519. errRefNum   –1280  bad connection reference number
  4520.  
  4521. The parameter block for the dspCLRemove command looks like this:
  4522.  
  4523. Parameter block
  4524.   ¨  16  ioResult  word  result code 
  4525.   Æ  26  csCode  word  always dspCLRemove
  4526.   Æ  32  ccbRefNum  word  reference number of connection 
  4527.           listener
  4528.   Æ  34  abort  byte  abort connection listener if not 0
  4529.  
  4530. The dspCLRemove command closes a connection end used as a connection listener.
  4531. You can release the memory you allocated for the connection control block if you
  4532. do not intend to reopen the connection end. 
  4533.  
  4534. The ioResult parameter returns the result of the function; in the case that you
  4535. call the function asynchronously, the function sets this field to 1 as soon as
  4536. it begins execution, and changes the field to the actual result code when it
  4537. completes execution. The csCode parameter is the routine selector; you should
  4538. set this to dspCLRemove for this command. The ccbRefNum parameter is the
  4539. connection control block reference number that was returned by the dspCLInit
  4540. command. If the abort parameter is nonzero, ADSP cancels any outstanding
  4541. requests to send packets (such as the dspCLDeny command). 
  4542.  
  4543. Result codes
  4544. noErr          0  no error
  4545. errRefNum  –1280  bad connection reference number
  4546. _______________________________________________________________________________
  4547.  
  4548. æKY Maintaining…an…ADSP…Connection
  4549. æC »Maintaining an ADSP Connection                                       AppleTalk Manager
  4550. _______________________________________________________________________________
  4551.  
  4552. Once you have established a connection end and opened a connection, you must be
  4553. able to send and receive data over the connection. You can use the functions in
  4554. this section to
  4555.  
  4556.   •   determine the status of a connection
  4557.   •   read bytes from the connection end’s receive queue
  4558.   •   write bytes to the connection end’s send queue and transmit them to the
  4559.       remote connection end
  4560.   •   send an attention message to the remote connection end
  4561.   •   discard all data that has been sent but not yet delivered, and reset the
  4562.       connection
  4563.  
  4564. The parameter block for the dspStatus command looks like this:
  4565.  
  4566. Parameter block
  4567.   ¨  16  ioResult  word  result code 
  4568.   Æ  26  csCode  word  always dspStatus
  4569.   Æ  32  ccbRefNum  word  reference number of connection end
  4570.   ¨  34  statusCCB  pointer  pointer to connection control block
  4571.   ¨  38  sendQPending  word  bytes waiting to be sent or 
  4572.           acknowledged
  4573.   ¨  40  sendQFree  word  available send queue in bytes
  4574.   ¨  42  recvQPending  word  bytes waiting to be read from queue
  4575.   ¨  44  recvQFree  word  available receive queue in bytes 
  4576.  
  4577. The dspStatus command returns the number of bytes waiting to be read and sent
  4578. and the space available in the send and receive queues. This function also
  4579. returns a pointer to the connection control block, which contains information
  4580. about the state of the connection end and about connection events received by
  4581. the connection end. The connection control block is described in “The ADSP
  4582. Connection Control Block” earlier in this chapter.
  4583.  
  4584. The ioResult parameter returns the result of the function; in the case that you
  4585. call the function asynchronously, the function sets this field to 1 as soon as
  4586. it begins execution, and changes the field to the actual result code when it
  4587. completes execution. The csCode parameter is the routine selector; you should
  4588. set this to dspStatus for this command. The ccbRefNum parameter is the
  4589. connection control block reference number that was returned by the dspInit
  4590. command. The statusCCB parameter returns a pointer to the connection control
  4591. block.
  4592.  
  4593. The sendQPending parameter indicates the number of bytes of data in the send
  4594. queue, including one byte for each end-of-message (EOM) indicator in the send
  4595. queue. (ADSP counts one byte for each EOM, even though there is no actual data
  4596. corresponding to the end-of-message indicator.) The send queue contains all data
  4597. that has been sent to ADSP for transmission that has not yet been acknowledged.
  4598. Some of the data in the send queue might have already been transmitted, but ADSP
  4599. retains it in the send queue until the remote connection end acknowledges its
  4600. receipt in case the data has to be retransmitted. The sendQFree parameter
  4601. indicates the buffer space available for additional data in the send queue, in
  4602. bytes. 
  4603.  
  4604. The recvQPending parameter indicates the number of bytes in the receive queue,
  4605. including one byte for each EOM if the end-of-message bit is set in an ADSP
  4606. packet header. The receive queue contains all of the data that has been received
  4607. by the connection end but not yet read by the connection end’s client. The
  4608. recvQFree parameter indicates the buffer space available for additional data in
  4609. the receive queue, in bytes.
  4610.  
  4611. Result codes
  4612. noErr          0  no error
  4613. errRefNum  –1280  bad connection reference number
  4614.  
  4615. The parameter block for the dspRead command looks like this:
  4616.  
  4617. Parameter block
  4618.   ¨  16  ioResult  word  result code 
  4619.   Æ  26  csCode  word  always dspRead
  4620.   Æ  32  ccbRefNum  word  reference number of connection end
  4621.   Æ  34  reqCount  word  requested number of bytes
  4622.   ¨  36  actCount  word  actual number of bytes read
  4623.   Æ  38  dataPtr  pointer  pointer to data buffer
  4624.   ¨  42  eom  byte  1 if end-of-message; 0 otherwise
  4625.  
  4626. The dspRead command reads bytes from the connection end’s receive queue and
  4627. places them in a buffer that you specify. You can continue to read bytes as long
  4628. as there is data in the receive queue, even after you or the remote end have
  4629. called the dspClose or dspRemove commands. The dspRead command completes
  4630. execution when it has read the number of bytes you specify, or when it
  4631. encounters an end-of-message (that is, the last byte of data in an ADSP packet
  4632. that has the end-of-message bit set in the packet header).
  4633.  
  4634. You can call the dspStatus command to determine the number of bytes remaining to
  4635. be read from the read queue, or you can continue to call the dspRead command
  4636. until the actCount and eom parameters both return 0.
  4637.  
  4638. The ioResult parameter returns the result of the function; in the case that you
  4639. call the function asynchronously, the function sets this field to 1 as soon as
  4640. it begins execution, and changes the field to the actual result code when it
  4641. completes execution. The csCode parameter is the routine selector; you should
  4642. set this to dspRead for this command. The ccbRefNum parameter is the connection
  4643. control block reference number that was returned by the dspInit command. 
  4644. You specify the number of bytes to read with the reqCount parameter, and use the
  4645. dataPtr parameter to provide a pointer to the buffer into which ADSP should
  4646. place the data. ADSP returns the actual number of bytes read in the actCount
  4647. parameter. If the last byte read constitutes an end-of-message, ADSP sets the
  4648. eom parameter to 1.
  4649.  
  4650. Result codes
  4651. noErr            0  no error
  4652. errFwdReset  –1275  read terminated by forward reset
  4653. errState     –1278  state isn’t open, closing, or closed
  4654. errAborted   –1279  request aborted by dspRemove or dspClose command
  4655. errRefNum    –1280  bad connection reference number
  4656.  
  4657. The parameter block for the dspWrite command looks like this:
  4658.  
  4659. Parameter block
  4660.   ¨  16  ioResult  word  result code 
  4661.   Æ  26  csCode  word  always dspWrite
  4662.   Æ  32  ccbRefNum  word  reference number of connection end
  4663.   Æ  34  reqCount  word  requested number of bytes
  4664.   ¨  36  actCount  word  actual number of bytes written
  4665.   Æ  38  dataPtr  pointer  pointer to data buffer
  4666.   Æ  42  eom  byte  1 if end of message; 0 otherwise
  4667.   Æ  43  flush  byte  1 to send data now; 0 otherwise
  4668.  
  4669. The dspWrite command writes bytes into the connection end’s send queue. The send
  4670. queue contains all data that has been sent to ADSP for transmission that has not
  4671. yet been acknowledged. Some of the data in the send queue might have already
  4672. been transmitted, but ADSP retains it in the send queue until the remote
  4673. connection end acknowledges its receipt in case the data has to be
  4674. retransmitted. The dspWrite command completes execution when it has copied all
  4675. of the data from the data buffer into the ADSP send queue.
  4676.  
  4677. ADSP transmits the data in the send queue when the remote connection end has
  4678. room to accept the data and one of the following conditions occurs:
  4679.  
  4680.   •   You call the dspWrite command with the flush parameter set to a nonzero
  4681.       number.
  4682.  
  4683.   •   The number of bytes in the send queue equals or exceeds the blocking
  4684.       factor; you use the sendBlocking parameter to the dspOptions command to
  4685.       set the blocking factor.
  4686.  
  4687.   •   The send timer expires.
  4688.  
  4689.   •   A connection event requires that the local connection end send an
  4690.       acknowlegment packet to the remote connection end.
  4691.  
  4692. The ioResult parameter returns the result of the function; in the case that you
  4693. call the function asynchronously, the function sets this field to 1 as soon as
  4694. it begins execution, and changes the field to the actual result code when it
  4695. completes execution. The csCode parameter is the routine selector; you should
  4696. set this to dspWrite for this command. The ccbRefNum parameter is the connection
  4697. control block reference number that was returned by the dspInit command. 
  4698.  
  4699. You specify the number of bytes to write with the reqCount parameter, and use
  4700. the dataPtr parameter to provide a pointer to the buffer from which ADSP should
  4701. read the data. The dspWrite command returns the actual number of bytes written
  4702. in the actCount parameter. If the last byte written constitutes an
  4703. end-of-message, set the eom parameter to 1. You can also set the reqCount
  4704. parameter to 0 and the eom parameter to 1 to indicate that the last byte you
  4705. sent the previous time you called the dspWrite command was the end of the
  4706. message. 
  4707.  
  4708. You can set the reqCount parameter to a value larger than the size of the send
  4709. queue. If you do so, the dspWrite command writes as much data as it can into the
  4710. send queue, sends the data and waits for acknowledgement, and then writes more
  4711. data into the send queue until it has written the amount of data you requested.
  4712. In this case, the function does not complete execution until it has finished
  4713. writing all of the data into the send queue. 
  4714.  
  4715. The high-order bits of the eom parameter are reserved for use by ADSP; you must
  4716. leave these bits equal to 0.
  4717.  
  4718. Set the flush parameter to 1 to cause ADSP to immediately transmit any data in
  4719. the send queue that has not already been transmitted. Set the flush parameter to
  4720. 0 to allow data to accumulate in the send queue until another condition occurs
  4721. that causes data to be transmitted. The high-order bits of the flush parameter
  4722. are reserved for use by ADSP; you must leave these bits equal to 0.
  4723.  
  4724. Result codes
  4725. noErr           0  no error
  4726. errState    –1278  connection is not open
  4727. errAborted  –1279  request aborted by dspRemove or dspClose command
  4728. errRefNum   –1280  bad connection reference number
  4729.  
  4730. The parameter block for the dspAttention command looks like this:
  4731.  
  4732. Parameter block
  4733.   ¨  16  ioResult  word  result code 
  4734.   Æ  26  csCode  word  always dspAttention
  4735.   Æ  32  ccbRefNum  word  reference number of connection end
  4736.   Æ  34  attnCode  word  client attention code
  4737.   Æ  36  attnSize  word  size of attention data in bytes
  4738.   Æ  38  attnData  pointer  pointer to attention data
  4739.  
  4740. The dspAttention command sends an attention code and an attention message to the
  4741. remote connection end. Attention codes and attention messages can have any
  4742. meaning that your application and the application at the remote connection end
  4743. both recognize. The purpose of attention codes and messages is to allow clients
  4744. of ADSP to send messages outside the normal data stream. For example, if a
  4745. connection end on a mainframe computer is connected to several connection ends
  4746. in Macintosh computers being used as remote terminals, the mainframe computer
  4747. might wish to inform the remote terminals that all connections will be
  4748. terminated in ten minutes. The mainframe application could send an attention
  4749. message to each of the remote terminals informing them of this fact, and the
  4750. terminal emulation programs in the Macintosh computers could then display an
  4751. alert message on the screen so that the users could prepare to shut down.
  4752.  
  4753. The ioResult parameter returns the result of the function; in the case that you
  4754. call the function asynchronously, the function sets this field to 1 as soon as
  4755. it begins execution, and changes the field to the actual result code when it
  4756. completes execution. The csCode parameter is the routine selector; you should
  4757. set this to dspAttention for this command. The ccbRefNum parameter is the
  4758. connection control block reference number that was returned by the dspInit
  4759. command. 
  4760.  
  4761. The attnCode parameter is the attention code that you wish to send to the remote
  4762. connection end. You can use any value from $0000 through $EFFF for the attention
  4763. code. The values $F000 through $FFFF are reserved for use by ADSP. The attnSize
  4764. parameter is the size in bytes of the attention message you wish to send, and
  4765. the attnData parameter provides a pointer to the attention message. The
  4766. attention message can be any size from 0 through 570 bytes. There are no
  4767. restrictions on the content of the attention message.
  4768.  
  4769. Result codes
  4770. noErr             0  no error
  4771. errAttention  –1276  attention message too long
  4772. errState      –1278  connection is not open
  4773. errAborted    –1279  request aborted by dspRemove or dspClose command
  4774. errRefNum     –1280  bad connection reference number
  4775.  
  4776. The parameter block for the dspReset command looks like this:
  4777.  
  4778. Parameter block
  4779.   ¨  16  ioResult  word  result code 
  4780.   Æ  26  csCode  word  always dspReset
  4781.   Æ  32  ccbRefNum  word  reference number of connection end
  4782.  
  4783. The dspReset command causes ADSP to discard all data in the send queue, all data
  4784. in transit to the remote connection end, and all data in the remote connection
  4785. end’s receive queue that the client has not yet read. This process is known as a
  4786. forward reset. ADSP then resynchronizes the connection. You can determine that
  4787. your connection end has received a forward reset and has discarded all data in
  4788. the receive queue by checking the eFwdReset flag in the userFlags field of the
  4789. connection control block. The connection control block is described in “The ADSP
  4790. Connection Control Block” earlier in this chapter. 
  4791.  
  4792. The ioResult parameter returns the result of the function; if you call the
  4793. function asynchronously, the function sets this field to 1 as soon as it begins
  4794. execution, and changes the field to the actual result code when it completes
  4795. execution. The csCode parameter is the routine selector; you should set this to
  4796. dspReset for this command. The ccbRefNum parameter is the connection control
  4797. block reference number that was returned by the dspInit command. 
  4798.  
  4799. Result codes
  4800. noErr           0  no error
  4801. errState    –1278  connection is not open
  4802. errAborted  –1279  request aborted by dspRemove or dspClose command
  4803. errRefNum   –1280  bad connection reference number
  4804. _______________________________________________________________________________
  4805.  
  4806. æKY The….ATP…Driver
  4807. æC »THE .ATP DRIVER                                                      AppleTalk Manager
  4808. _______________________________________________________________________________
  4809.  
  4810. AppleTalk Phase 2 includes two changes to the .ATP driver: you can now cancel
  4811. all calls to the ATPGetRequest function that are pending execution, and you can
  4812. now set the release timer for ATP exactly-once (XO) service to one of five
  4813. different values. 
  4814. _______________________________________________________________________________
  4815.  
  4816. æKY Canceling…All…Calls…to…the…ATPGetRequest…Function
  4817. æC »Canceling All Calls to the ATPGetRequest Function                    AppleTalk Manager
  4818. _______________________________________________________________________________
  4819.  
  4820. The ATPGetRequest function sets a socket to receive a request sent by another
  4821. socket. If you call the ATPGetRequest function asynchronously, you can have
  4822. several calls to the function simultaneously pending execution. The
  4823. ATPKillAllGetReq function cancels all calls to the ATPGetRequest function
  4824. pending for a specific socket without closing the socket. 
  4825.  
  4826. FUNCTION ATPKillAllGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  4827.  
  4828. Parameter block
  4829.   Æ  26  csCode  word  always ATPKillAllGetReq
  4830.   Æ  28  atpSocket  byte  socket for which to cancel all calls to ATPGetRequest
  4831.  
  4832. The ATPKillAllGetReq function cancels all pending asynchronous calls to the
  4833. ATPGetRequest function for the socket you specify with the atpSocket parameter.
  4834. Unlike the ATPCloseSocket function, the ATPKillAllGetReq function does not close
  4835. the socket. You should call the ATPKillAllGetReq function before closing a
  4836. socket. The csCode parameter is a routine selector, automatically set by the MPW
  4837. interface. It is always equal to ATPKillAllGetReq for this function.
  4838.  
  4839. Result codes
  4840. noErr           0  no error
  4841. cbNotFound  –1102  control block not found; no pending asynchronous calls
  4842. _______________________________________________________________________________
  4843.  
  4844. æKY Setting…the…Timeout…Value…For…the…ATP…Release…Timer
  4845. æC »Setting the Timeout Value For the ATP Release Timer                  AppleTalk Manager
  4846. _______________________________________________________________________________
  4847.  
  4848. The .ATP driver maintains a timer, called the release timer, for each call to
  4849. the PSendResponse function that is part of an exactly-once transaction. If the
  4850. timer expires before the transaction is complete (that is, before the socket
  4851. receives the transaction release packet), the driver completes the PSendResponse
  4852. function. Before AppleTalk Phase 2, the release timer was always set to 30
  4853. seconds. To set the other connection end’s release timer to another value, set
  4854. bit 2 of the atpFlags field in the parameter block for the PSendRequest or the
  4855. PNSendRequest function and add a new field to the parameter block at offset 50:
  4856. the TRelTime field. The lower three bits of the TRelTime field indicate the time
  4857. to which the release timer is to be set, as follows:
  4858.  
  4859. TRelTime Field  Setting of Release Timer
  4860. 000             30 seconds
  4861. 001             1 minute
  4862. 010             2 minutes
  4863. 011             4 minutes
  4864. 100             8 minutes
  4865.  
  4866. Note:  The nodes at both ends of the ATP connection must be running AppleTalk
  4867. Phase 2 drivers for this feature to work.
  4868.  
  4869. Exactly-once service, the release timer, and the PSendRequest function are
  4870. described in the AppleTalk Manager chapter of Volume II. The ATP parameter block
  4871. and the PSendRequest function are described in the AppleTalk Manager chapter of
  4872. Volume V.
  4873.  
  4874. _______________________________________________________________________________
  4875.  
  4876. æKY The….XPP…Driver
  4877. æC »THE .XPP DRIVER                                                      AppleTalk Manager
  4878. _______________________________________________________________________________
  4879.  
  4880. The .XPP driver provides these functions that return information about zones:
  4881.  
  4882.   •   The GetMyZone function returns the AppleTalk zone name of the node on
  4883.       which your application is running.
  4884.  
  4885.   •   The GetLocalZones function returns a list of zone names on the network
  4886.       that includes the node on which your application is running.
  4887.  
  4888.   •   The GetZoneList function returns a complete list of zones on the internet.
  4889.  
  4890. Note:  Before the AppleTalk Phase 2 version of the .XPP driver, you had to use
  4891. ATP to obtain zone information and request it directly from a router. The ZIP
  4892. functions provided by the new version of the .XPP driver make it much easier for
  4893. you to obtain this information. To ensure compatibility with future versions of
  4894. AppleTalk, you should always use the functions described in this section to
  4895. obtain zone information.  
  4896.  
  4897. The .XPP driver uses a parameter block defined by the xCallParam record for the
  4898. GetMyZone, GetLocalZones, and GetZoneList functions.
  4899.  
  4900. xCallParam = PACKED RECORD
  4901.   qLink:         QElemPtr;  {next queue entry}
  4902.   qType:         INTEGER;  {queue type}
  4903.   ioTrap:        INTEGER;  {routine trap}
  4904.   ioCmdAddr:     Ptr;      {routine address}
  4905.   ioCompletion:  ProcPtr;  {completion routine}
  4906.   ioResult:      OsErr;    {result code}
  4907.   ioNamePtr:     StringPtr;{used only for Open routine}
  4908.   ioVRefNum:     INTEGER;  {volume reference number}
  4909.   ioRefNum:      INTEGER;  {driver reference number}
  4910.   csCode:        INTEGER;  {primary command code}
  4911.   xppSubCode:    INTEGER;  {secondary command code}
  4912.   xppTimeOut:    Byte;     {timeout period for .XPP}
  4913.   xppRetry:      Byte;     {retry count}
  4914.   filler:        INTEGER;  {reserved}
  4915.   zipBuffPtr:    Ptr;      {returned zone names}
  4916.   zipNumZones:   INTEGER;  {number of zones returned}
  4917.   zipLastFlag:   Byte;     {nonzero when all zone names have been returned}
  4918.   filler        Byte;    {reserved}
  4919.   zipInfoField:  PACKED ARRAY[1..70] of Byte {reserved for use by .XPP}
  4920. END;
  4921.  
  4922. XCallParamPtr = ^XCallParam;
  4923.  
  4924. As for all other AppleTalk Manager preferred interface functions, the MPW
  4925. interface calls the Device Manager PBControl function to implement these ZIP
  4926. protocol functions. The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and
  4927. ioVRefNum fields are filled in by the Device Manager; your application should
  4928. not have to set or read these parameters. The ioResult parameter returns the
  4929. result of the function; in the case that you call the function asynchronously,
  4930. the Device Manager sets this field to 1 as soon as you call the function, and
  4931. changes the field to the actual result code when the function completes
  4932. execution. The ioCompletion parameter is a pointer to a completion routine that
  4933. you can provide; the Device Manager calls your completion routine when it
  4934. completes execution of the PBControl function. If you are not providing a
  4935. completion routine, specify NIL for this field. The ioRefNum, csCode, and
  4936. xppSubCode fields specify the driver and the command to be executed; the MPW
  4937. Pascal interface fills in these fields for you.
  4938.  
  4939. _______________________________________________________________________________
  4940.  
  4941. æKY Using…the….XPP…Driver…to…Obtain…Zone…Information
  4942. æC »Using the .XPP Driver to Obtain Zone Information                     AppleTalk Manager
  4943. _______________________________________________________________________________
  4944.  
  4945. The Zone Information Protocol obtains the zone information by using the
  4946. AppleTalk Transaction Protocol to send an information request to a router. The
  4947. xppTimeOut field specifies the amount of time, in seconds, that the .ATP driver
  4948. should wait between attempts to obtain the data. The xppRetry field specifies
  4949. the number of times the .ATP driver should attempt to obtain the data before
  4950. returning the reqFailed (request failed) result code. 
  4951.  
  4952. The zipBuffPtr field is a pointer to a data buffer that you must allocate. This
  4953. buffer must be 578 bytes for the GetZoneList and GetLocalZones functions and 33
  4954. bytes for the GetMyZone function. The Zone Information Protocol returns the zone
  4955. names (as a packed array of packed Pascal strings) into this buffer. The
  4956. zipNumZones field returns the actual number of zone names that ZIP placed in the
  4957. buffer. You must set the zipLastFlag field to 0 before you execute the
  4958. GetZoneList or GetLocalZones functions. If the zipLastFlag parameter is still 0
  4959. when the command has completed execution, then the ZIP is waiting to return more
  4960. zone names. In this case you must empty the buffer (or allocate a new one) and
  4961. call the GetZoneList or GetLocalZones function again immediately. When there are
  4962. no more zone names to send, ZIP sets the zipLastFlag field to a nonzero value.
  4963.  
  4964. The zipInfoField field is a 70-byte data buffer that you must allocate for use
  4965. by the .XPP driver. The first time you call any of these functions, you must set
  4966. the first word of this field to 0. You must not change any values in this field
  4967. subsequently.
  4968.  
  4969. Listing 29-5 illustrates the use of the GetZoneList function. The GetLocalZones
  4970. function operates in exactly the same fashion.
  4971.  
  4972. Listing 29-5.  Using the GetZoneList function (TO BE PROVIDED)
  4973.  
  4974. Listing 29-6 illustrates the use of the GetMyZone function. 
  4975.  
  4976. Listing 29-6.  Using the GetMyZone function (TO BE PROVIDED)
  4977. _______________________________________________________________________________
  4978.  
  4979. æKY XPP…Driver…Routines
  4980. æC »XPP Driver Routines                                                  AppleTalk Manager
  4981. _______________________________________________________________________________
  4982.  
  4983. The .XPP driver provides three functions that obtain information about zones.
  4984. All three functions use the Zone Information Protocol to return the names of
  4985. zones: The GetMyZone function returns the AppleTalk zone name of the node on
  4986. which your application is running; the GetLocalZones function returns a list of
  4987. zone names on the network that includes the node on which your application is
  4988. running; and the GetZoneList function returns a complete list of zones on the
  4989. internet.
  4990.  
  4991. Assembly-language note:  The .XPP driver functions all use the same value
  4992. (xCall, which is equal to 246) for the csCode parameter to the xCallParam
  4993. parameter block. The xCall routine uses the value of the xppSubCode parameter to
  4994. distinguish between the functions, as follows:
  4995.  
  4996. Function        xppSubCode      Value
  4997. GetMyZone       getMyZone       7
  4998. GetLocalZones   getLocalZones   5
  4999. GetZoneList     getZoneList     6
  5000.  
  5001. FUNCTION GetMyZone (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  5002.  
  5003. Parameter block
  5004.   ¨  16  ioResult  word  result code 
  5005.   Æ  26  csCode  word  routine selector; always xCall
  5006.   Æ  28  xppSubCode  word  routine selector; getMyZone
  5007.   Æ  30  xppTimeOut  byte  retry interval in seconds
  5008.   Æ  31  xppRetry  byte  retry count
  5009.   Æ  34  zipBuffPtr  long  pointer to data buffer
  5010.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  5011.  
  5012. The GetMyZone function returns only the zone name of the node on which your
  5013. application is running.
  5014.  
  5015. The ioResult parameter returns the result of the function; if you call the
  5016. function asynchronously, the function sets this field to 1 as soon as it begins
  5017. execution, and changes the field to the actual result code when it completes
  5018. execution. The csCode and xppSubCode parameters are routine selectors and are
  5019. automatically set by the MPW interface to xCall and getMyZone for this function.
  5020. The xppTimeOut field specifies the amount of time, in seconds, that the .ATP
  5021. driver should wait between attempts to obtain the data. A value of 3 or 4 for
  5022. the xppTimeOut field generally gives good results. The xppRetry field specifies
  5023. the number of times the .ATP driver should attempt to obtain the data before
  5024. returning the ReqFailed (request failed) result code. A value of 3 or 4 for the
  5025. xppRetry field usually works well.
  5026.  
  5027. The zipBuffPtr is a pointer to a 33-byte data buffer that you must allocate. The
  5028. Zone Information Protocol returns the zone name into this buffer as a Pascal
  5029. string. The zipInfo field is a 70-byte data buffer that you must allocate for
  5030. use by ZIP. You must set the first word of this buffer to 0 before you call the
  5031. GetMyZone function.
  5032.  
  5033. Result codes
  5034. noErr          0  no error
  5035. noBridgeErr  –93  no router is available
  5036. reqFailed  –1096  Request to contact router failed; retry count exceeded 
  5037.  
  5038. FUNCTION GetLocalZones (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  5039.  
  5040. Parameter block
  5041.   ¨  16  ioResult  word  result code 
  5042.   Æ  26  csCode  word  routine selector; always xCall
  5043.   Æ  28  xppSubCode  word  routine selector; getLocalZones
  5044.   Æ  30  xppTimeOut  byte  retry interval in seconds
  5045.   Æ  31  xppRetry  byte  retry count
  5046.   Æ  34  zipBuffPtr  pointer  pointer to data buffer
  5047.   ¨  38  zipNumZones  word  number of names returned
  5048.   ¨  40  zipLastFlag  byte  nonzero if no more names
  5049.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  5050.  
  5051. The GetLocalZones function returns a list of all the zone names on the local
  5052. network; that is, the network that includes the node on which your application
  5053. is running.
  5054.  
  5055. The ioResult parameter returns the result of the function; if you call the
  5056. function asynchronously, the function sets this field to 1 as soon as it begins
  5057. execution, and changes the field to the actual result code when it completes
  5058. execution. The csCode and xppSubCode parameters are routine selectors and are
  5059. automatically set by the MPW interface to xCall and getLocalZones for this
  5060. function. The xppTimeOut field specifies the amount of time, in seconds, that
  5061. the .ATP driver should wait between attempts to obtain the data. A value of 3 or
  5062. 4 for the xppTimeOut field generally gives good results. The xppRetry field
  5063. specifies the number of times the .ATP driver should attempt to obtain the data
  5064. before returning the ReqFailed (request failed) result code. A value of 3 or 4
  5065. for the xppRetry field usually works well.
  5066.  
  5067. The zipBuffPtr is a pointer to a 578-byte data buffer that you must allocate.
  5068. The Zone Information Protocol returns the zone names into this buffer as a
  5069. packed array of packed Pascal strings. The zipNumZones parameter returns the
  5070. number of zone names that ZIP placed in the data buffer. 
  5071.  
  5072. The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
  5073. for your network. If the zipLastFlag field is still 0 when the GetLocalZones
  5074. function has completed execution, you must empty the data buffer pointed to by
  5075. the zipBuffPtr parameter and immediately call the GetLocalZones function again
  5076. without changing the value in the zipInfoField parameter. The zipInfofield
  5077. parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
  5078. must set the first word of this buffer to 0 before you call the GetLocalZones
  5079. function the first time, and not change the contents of this field thereafter.
  5080.  
  5081. FUNCTION GetZoneList (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  5082.  
  5083. Parameter block
  5084.   ¨  16  ioResult  word  result code 
  5085.   Æ  26  csCode  word  routine selector; always xCall
  5086.   Æ  28  xppSubCode  word  routine selector; getZoneList
  5087.   Æ  30  xppTimeOut  byte  retry interval in seconds
  5088.   Æ  31  xppRetry  byte  retry count
  5089.   Æ  34  zipBuffPtr  pointer  pointer to data buffer
  5090.   ¨  38  zipNumZones  word  number of names returned
  5091.   ¨  40  zipLastFlag  byte  nonzero if no more names
  5092.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  5093.  
  5094. The GetZoneList function returns a complete list of all the zone names on the
  5095. internet. Use the GetLocalZones function to obtain a list of only the zone names
  5096. on the local network. 
  5097.  
  5098. The ioResult parameter returns the result of the function; if you call the
  5099. function asynchronously, the function sets this field to 1 as soon as it begins
  5100. execution, and changes the field to the actual result code when it completes
  5101. execution. The csCode and xppSubCode parameters are routine selectors and are
  5102. automatically set by the MPW interface to xCall and getZoneList for this
  5103. function. The xppTimeOut field specifies the amount of time, in seconds, that
  5104. the .ATP driver should wait between attempts to obtain the data. A value of 3 or
  5105. 4 for the xppTimeOut field generally gives good results. The xppRetry field
  5106. specifies the number of times the .ATP driver should attempt to obtain the data
  5107. before returning the ReqFailed (request failed) result code. A value of 3 or 4
  5108. for the xppRetry field usually works well.
  5109.  
  5110. The zipBuffPtr is a pointer to a 578-byte data buffer that you must allocate.
  5111. The Zone Information Protocol returns the zone names into this buffer as Pascal
  5112. strings. The zipNumZones parameter returns the number of zone names that ZIP
  5113. placed in the data buffer. 
  5114.  
  5115. The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
  5116. for the internet. If the zipLastFlag field is still 0 when the GetZoneList
  5117. function has completed execution, you must empty the data buffer pointed to by
  5118. the zipBuffPtr parameter and immediately call the GetZoneList function again
  5119. without changing the value in the zipInfoField parameter. The zipInfofield
  5120. parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
  5121. must set the first word of this buffer to 0 before you call the GetZoneList
  5122. function the first time, and not change the contents of this field thereafter.
  5123.  
  5124. _______________________________________________________________________________
  5125.  
  5126. æKY The….ENET…Driver
  5127. æC »THE .ENET DRIVER                                                     AppleTalk Manager
  5128. _______________________________________________________________________________
  5129.  
  5130. The .ENET driver is an Ethernet driver for the EtherTalk NuBus card that is
  5131. manufactured by Apple Computer, Inc. The .ENET driver is normally called by the
  5132. AppleTalk Manager through the EtherTalk 'adev' file when the user has selected
  5133. EtherTalk from the Network control panel. You can write your own protocol stack
  5134. or application that uses the .ENET driver directly, rather than through
  5135. AppleTalk. This section describes how to open the .ENET driver, how to send data
  5136. to it directly for transmission over the Ethernet network, and how to write a
  5137. protocol handler to receive data from the network.
  5138.  
  5139. If you write an Ethernet driver for use with your own Ethernet NuBus card, you
  5140. should provide the features and functions described in this chapter and should
  5141. name your driver .ENET. If you write an Ethernet driver for use with a non-NuBus
  5142. network interface (such as an Ethernet card for the Macintosh SE/30 or an
  5143. Ethernet connection through the SCSI port), you should provide the features and
  5144. functions described in this chapter for the .ENET driver and should name your
  5145. driver .ENET0. If you do so, any software written to use the .ENET driver should
  5146. work with your driver.
  5147.  
  5148. _______________________________________________________________________________
  5149.  
  5150. æKY Changing…the…Ethernet…Hardware…Address
  5151. æC »Changing the Ethernet Hardware Address                               AppleTalk Manager
  5152. _______________________________________________________________________________
  5153.  
  5154. Each Ethernet NuBus card or other Ethernet hardware interface device contains a
  5155. unique 6-byte hardware address assigned by the manufacturer of the device. The 
  5156. .ENET driver normally uses this address to determine whether to receive a
  5157. packet. To change the hardware address for your node, place in the System file a
  5158. resource of type 'eadr' with a resource ID equal to the slot number of the
  5159. Ethernet NuBus card. If the Ethernet device is not a NuBus card (it might be a
  5160. slot card in a Macintosh SE/30, for example), use a resource ID of 0. 
  5161.  
  5162. The 'eadr' resource consists only of a 6-byte number. Do not use the broadcast
  5163. address or a multicast address for this number. (The broadcast address is
  5164. $FF-FF-FF-FF-FF-FF. A multicast address is any Ethernet address in which the
  5165. low-order bit of the high-order byte is set to 1.) When you open the .ENET
  5166. driver, it looks for an 'eadr' resource. If it finds one, the driver substitutes
  5167. the number in this resource for the Ethernet hardware address and uses it until
  5168. the driver is closed or reset. 
  5169.  
  5170. Note:  To avoid address collisions, you should never arbitrarily change the
  5171. Ethernet hardware address. This feature should be used only by a system
  5172. adiministrator who can keep track of all the Ethernet addresses in the system.
  5173.  
  5174. _______________________________________________________________________________
  5175.  
  5176. æKY Opening…the….ENET…Driver
  5177. æC »Opening the .ENET Driver                                             AppleTalk Manager
  5178. _______________________________________________________________________________
  5179.  
  5180. Before you use the OpenSlot function to open the .ENET driver, you must
  5181. determine which NuBus slots contain EtherTalk cards. The OpenSlot function is
  5182. described in the Device Manager chapter of Volume V. Use the GetsRsrc function
  5183. described in the Slot Manager chapter of this volume to determine which NuBus
  5184. slots contain cards and the type of each NuBus card installed. EtherTalk NuBus
  5185. cards return the string CatNetwork in the field spCategory of the GetsRsrc
  5186. function parameter block, and return the string TypEthernet in the field spType.
  5187.  
  5188. Listing 29-7 illustrates the use of the GetsRsrc function and the OpenSlot
  5189. function to open the .ENET driver.
  5190.  
  5191. Listing 29-7.  Finding an EtherTalk card and opening the .ENET Driver (TO BE
  5192. PROVIDED)
  5193. _______________________________________________________________________________
  5194.  
  5195. æKY Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
  5196. æC »Using a Write-Data Structure to Transmit Ethernet Data               AppleTalk Manager
  5197. _______________________________________________________________________________
  5198.  
  5199. When you use the EWrite function to send data to the .ENET driver for
  5200. transmission over the Ethernet network, you provide a pointer to a write-data
  5201. structure (Figure 29-4). A write-data structure contains a series of pairs of
  5202. length words and pointers. Each pair indicates the length and location of a
  5203. portion of the data that constitutes the packet to be sent over the network. The
  5204. first length-pointer pair points to a 14-byte header block, which starts with
  5205. the destination node hardware address. Note that this is not the AppleTalk
  5206. address, but is the hardware address of the destination node. If you are calling
  5207. the .ENET driver directly, you must obtain the Ethernet address of the
  5208. destination node yourself; AppleTalk cannot provide it.
  5209.  
  5210. The next 6 bytes of the header block are reserved for use by the .ENET driver.
  5211. These bytes are followed by the 2-byte Ethernet protocol type. Data may follow
  5212. the header block; all other length-pointer pairs point to data. The write-data
  5213. structure terminates with a NIL word.
  5214.  
  5215. ø 29.3  Ethernet Write-Data Structure
  5216.  
  5217. When you first open the .ENET driver, it allocates a 768-byte buffer that it
  5218. uses for transmitting data packets. This buffer is large enough to hold the
  5219. largest EtherTalk packet, which is 617 bytes in size. If you want to transmit
  5220. data packets larger than 768 bytes, call the ESetGeneral function. The .ENET
  5221. driver then allocates a large enough data buffer to send packets up to 1514
  5222. bytes in size.
  5223.  
  5224. Listing 29-8 defines an Ethernet write-data structure and then calls the EWrite
  5225. function to send a data packet over Ethernet.
  5226.  
  5227. Listing 29-8.  Sending a Data Packet Over Ethernet (TO BE PROVIDED)
  5228. _______________________________________________________________________________
  5229.  
  5230. æKY Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
  5231. æC »Using the Default Ethernet Protocol Handler to Read Data             AppleTalk Manager
  5232. _______________________________________________________________________________
  5233.  
  5234. When the EtherTalk Nubus card or other Ethernet hardware receives a data packet,
  5235. it generates an interrupt to the CPU. The interrupt handler in ROM determines
  5236. the source of the interrupt and calls the .ENET driver. The .ENET driver reads
  5237. the packet header to determine the protocol type of the data packet and checks
  5238. to see if any client has specified that protocol type in a call to the EAttachPH
  5239. function. If so, the client either specified a NIL pointer to a protocol
  5240. handler, or the client provided its own protocol handler. If the client
  5241. specified a NIL pointer, the .ENET driver uses its default protocol handler to
  5242. read the data. If no one has specified that protocol type in a call to the
  5243. EAttachPH function, the .ENET driver discards the data. The EAttachPH function
  5244. is described in 
  5245. “Attaching and Detaching an Ethernet Protocol Handler” later in this chapter.
  5246.  
  5247. The default protocol handler checks for an ERead function pending execution and
  5248. places the entire packet—including the packet header—into the buffer specified
  5249. by that function. The function returns the number of bytes actually read. If the
  5250. packet is larger than the data buffer, the ERead function places as much of the
  5251. packet as will fit into the buffer and returns the buf2SmallErr result code.
  5252.  
  5253. Call the ERead function asynchronously to await the next data packet. When the 
  5254. .ENET driver receives the data packet, it completes execution of the ERead
  5255. function and calls your completion routine. Your completion routine should call
  5256. the ERead function again so that there is always an ERead function pending
  5257. execution. If the .ENET driver receives a data packet with a protocol type for
  5258. which you specified the default protocol handler, but there is no ERead function
  5259. pending, the .ENET driver discards the packet.
  5260.  
  5261. You can have several asynchronous calls to the ERead function pending execution
  5262. simultaneously, as long as you use a different parameter block for each call.
  5263.  
  5264. Listing 29-9 defines a completion routine.
  5265.  
  5266. Listing 29-9.  Using the Default Ethernet Protocol Handler to Read Data (TO BE
  5267. PROVIDED)
  5268.  
  5269. _______________________________________________________________________________
  5270.  
  5271. æKY Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
  5272. æC »Using Your Own Ethernet Protocol Handler to Read Data                AppleTalk Manager
  5273. _______________________________________________________________________________
  5274.  
  5275. If a client of the .ENET driver has used the EAttachPH function to provide a
  5276. pointer to its own protocol handler, the .ENET driver calls that protocol
  5277. handler, which must in turn call the .ENET driver’s ReadPacket and ReadRest
  5278. routines to read the data. Your protocol handler calls the .ENET driver’s
  5279. ReadPacket and ReadRest routines in essentially the same way as you call the
  5280. .MPP drivers ReadPacket and ReadRest routines (see the AppleTalk Manager chapter
  5281. of Volume II). The following sections describe the .ENET driver’s call to a
  5282. custom protocol handler and the ReadPacket and ReadRest routines.
  5283.  
  5284. Note:  Because an Ethernet protocol handler must read from and write to the 
  5285. CPU’s registers, you cannot write a protocol handler in Pascal. 
  5286. _______________________________________________________________________________
  5287.  
  5288. æKY How…the….ENET…Driver…Calls…Your…Protocol…Handler
  5289. æC »How the .ENET Driver Calls Your Protocol Handler                     AppleTalk Manager
  5290. _______________________________________________________________________________
  5291.  
  5292. You can provide an Ethernet protocol handler for a particular protocol type and
  5293. use the EAttachPH function to attach it to the .ENET driver. When the driver
  5294. receives an Ethernet packet, it reads the packet header into an internal buffer,
  5295. reads the protocol type, and calls the protocol handler for that protocol type.
  5296. The CPU is in interrupt mode and the registers are used as follows:
  5297.  
  5298. Registers on call to Ethernet protocol handler
  5299.  
  5300. A0
  5301. Reserved for internal use by the .ENET driver; you must preserve this register
  5302. until after the ReadRest routine has completed execution
  5303.  
  5304. A1
  5305. Reserved for internal use by the .ENET driver; you must preserve this register
  5306. until after the ReadRest routine has completed execution
  5307.  
  5308. A2  Free for your use
  5309.  
  5310. A3
  5311. Pointer to first byte past data-link header bytes (the first byte after the
  5312. 2-byte protocol-type field)
  5313.  
  5314. A4
  5315. Pointer to the ReadPacket routine; the ReadRest routine starts 2 bytes after the
  5316. start of the ReadPacket routine
  5317.  
  5318. A5
  5319. Free for your use until after the ReadRest routine has completed execution
  5320.  
  5321. D0  Free for your use
  5322.  
  5323. D1
  5324. Number of bytes in the Ethernet packet left to be read (that is, the number of
  5325. bytes following the Ethernet header) 
  5326.  
  5327. D2  Free for your use
  5328.  
  5329. D3  Free for your use
  5330.  
  5331. If your protocol handler processes more than one protocol type, you can read the
  5332. protocol-type field in the data-link header to determine the protocol type of
  5333. the packet. The protocol-type field starts 2 bytes before the address pointed to
  5334. by the A3 register. 
  5335.  
  5336. Note:  The source address starts 8 bytes before the address pointed to by the A3
  5337. register and the destination address starts 14 bytes before the address pointed
  5338. to by the A3 register.
  5339.  
  5340. If you know that the packet contains pad bytes and you know the actual size of
  5341. the data, you can reduce the number in the D1 register by the number of pad
  5342. bytes so that the .ENET driver can keep accurate track of the number of bytes
  5343. remaining to be read. In all other circumstances, you should not change the
  5344. value in the D1 register. 
  5345.  
  5346. After you have called the ReadRest routine, you can use registers A0 through A3
  5347. and D0 through D3 for your own use, and must preserve all other registers. You
  5348. cannot depend on having access to your application global variables.
  5349.  
  5350. _______________________________________________________________________________
  5351.  
  5352. æKY How…Your…Protocol…Handler…Calls…the….ENET…Driver
  5353. æC »How Your Protocol Handler Calls the .ENET Driver                     AppleTalk Manager
  5354. _______________________________________________________________________________
  5355.  
  5356. Your protocol handler must call the .ENET driver routines ReadPacket and
  5357. ReadRest to read the incoming data packet. You may call the ReadPacket routine
  5358. as many times as you like to read the data piece-by-piece into one or more data
  5359. buffers, but you must always use the ReadRest routine to read the final piece of
  5360. the data packet. The ReadRest routine restores the machine state (the stack
  5361. pointers, status register, and so forth) and checks for error conditions. 
  5362. Before you call the ReadPacket routine, you must allocate memory for a data
  5363. buffer and place a pointer to the buffer in the A3 register. You place the
  5364. number of bytes you want to read in the D3 register. You must not request more
  5365. bytes than remain in the data packet. 
  5366.  
  5367. To call the ReadPacket routine, execute a JSR instruction to the address in the
  5368. A4 register. The ReadPacket routine uses the registers as follows:
  5369.  
  5370. Registers on entry to the ReadPacket routine
  5371.  
  5372. A3  Pointer to a buffer to hold the data you want to read
  5373. D3  Number of bytes to read; must be nonzero
  5374.  
  5375. Registers on exit from the ReadPacket routine
  5376.  
  5377. A0  Unchanged
  5378. A1  Unchanged
  5379. A2  Unchanged
  5380. A3  Pointer to next byte to read (first byte after the last byte read)
  5381. D0  Changed
  5382. D1  Number of bytes left to be read
  5383. D2  Unchanged
  5384. D3  Equals 0 if requested number of bytes were read, nonzero if error
  5385.  
  5386. The ReadPacket routine indicates an error by clearing to 0 the zero (z) flag in
  5387. the status register. If the ReadPacket routine returns an error, you must
  5388. terminate execution of your protocol handler with an RTS instruction without
  5389. calling ReadPacket again or calling ReadRest at all.
  5390.  
  5391. Call the ReadRest routine to read the last portion of the data packet, or call
  5392. it after you have read all the data with ReadPacket routines and before you do
  5393. any other processing or terminate execution. You must provide in the A3 register
  5394. a pointer to a data buffer and must indicate in the D3 register the size of the
  5395. data buffer. If you have already read all of the data with calls to the
  5396. ReadPacket routine, you can specify a 0-size buffer.
  5397.  
  5398. †  Warning:  If you do not call the ReadRest routine after your last call to the
  5399. ReadPacket routine, the system will crash. Ê 
  5400.  
  5401. To call the ReadRest routine, execute a JSR instruction to an address 2 bytes
  5402. past the address in the A4 register. The ReadRest routine uses the registers as
  5403. follows:
  5404.  
  5405. Registers on entry to the ReadRest routine
  5406.  
  5407. A3  Pointer to a buffer to hold the data you want to read
  5408. D3  Size of the buffer (word length); may be 0
  5409.  
  5410. Registers on exit from the ReadRest routine
  5411.  
  5412. A0  Unchanged
  5413. A1  Unchanged
  5414. A2  Unchanged
  5415. A3  Pointer to first byte after the last byte read
  5416. D0  Changed
  5417. D1  Changed
  5418. D2  Unchanged
  5419. D3  Equals 0 if requested number of bytes were read; less than 0 if there was
  5420. more data left than would fit in buffer (extra data equals –D3 bytes); greater
  5421. than 0 if there was less data left than the size of the buffer (extra buffer
  5422. space equals D3 bytes)
  5423.  
  5424. If the buffer you provide is not large enough to hold the remaining bytes in the
  5425. packet, the ReadRest routine returns an error. The ReadRest routine indicates an
  5426. error by clearing to 0 the zero (z) flag in the status register. 
  5427.  
  5428. You must terminate execution of your protocol handler with an RTS instruction
  5429. whether or not the ReadRest routine returns an error.
  5430.  
  5431. _______________________________________________________________________________
  5432.  
  5433. æKY ENET…Driver…Routines
  5434. æC »ENET Driver Routines                                                 AppleTalk Manager
  5435. _______________________________________________________________________________
  5436.  
  5437. An application that uses AppleTalk Manager routines for network communications
  5438. can talk to whatever network the user has selected through the Network control
  5439. panel. However, you can choose to write an application that talks only to
  5440. Ethernet; in this case, your application has to address the Ethernet driver
  5441. directly. This section describes the functions that you can use to control the 
  5442. .ENET driver, the Ethernet driver provided with system software version 7.0.
  5443. Each.ENET driver function is of the form 
  5444.  
  5445. FUNCTION Efunc (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5446.  
  5447. where the thePBptr parameter is a pointer to the .ENET parameter block and the
  5448. async parameter is a Boolean that specifies whether the function is to be
  5449. executed synchronously or asynchronously. Set the async parameter to TRUE to
  5450. execute the function asynchronously.
  5451.  
  5452. The .ENET parameter block is defined as follows:
  5453.  
  5454. EParamBlock = PACKED RECORD
  5455.   qLink:   QElemPtr;  {next queue entry}
  5456.   qType:   INTEGER;  {queue type}
  5457.   ioTrap:   INTEGER;  {routine trap}
  5458.   ioCmdAddr:   Ptr;  {routine address}
  5459.   ioCompletion:   ProcPtr;  {completion routine}
  5460.   ioResult:   OsErr;  {result code}
  5461.   ioNamePtr:   StringPtr;  {driver name}
  5462.   ioVRefNum:   INTEGER;  {volume reference number}
  5463.   ioCRefNum:   INTEGER;  {driver reference number}
  5464.   csCode:   INTEGER;  {primary command code}
  5465.  
  5466.   CASE INTEGER OF
  5467.   EWrite,
  5468.   EAttachPH,
  5469.   EDetachPH,
  5470.   ERead,
  5471.   ERdCancel,
  5472.   EGetInfo,
  5473.   ESetGeneral:
  5474.     (
  5475.     EProtType:  INTEGER;  {Ethernet protocol type}
  5476.     EPointer:  Ptr;  {pointer; use depends on function}
  5477.     EBuffSize  INTEGER  {buffer size}
  5478.     EDataSize  INTEGER  {number of bytes read}
  5479.     );
  5480.  
  5481.   EAddMulti,
  5482.   EDelMulti:
  5483.     (
  5484.     EMultiAddr:  ?????;  {Multicast address}
  5485.     );
  5486. END;
  5487.  
  5488. The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are
  5489. standard parameters provided by the Pascal or C interface; your application
  5490. should not have to set or read these parameters. The ioResult parameter returns
  5491. the result of the function; in the case that you call the function
  5492. asynchronously, the function sets this field to 1 as soon as it begins
  5493. execution, and changes the field to the actual result code when it completes
  5494. execution. The ioCompletion parameter is a pointer to a completion routine that
  5495. you can provide; the Device Manager calls your completion routine when it
  5496. completes execution of the function. If you are not providing a completion
  5497. routine, specify NIL for this field. The ioCRefNum and csCode fields specify the
  5498. driver and the command to be executed; the MPW Pascal interface fills in these
  5499. fields for you. The Control function is discussed in the Device Manager chapter
  5500. of Volume II.
  5501.  
  5502. The remaining parameters are used only for specific functions; all of these
  5503. parameters are described in the following sections.
  5504.  
  5505. For a general discussion of the use of the Ethernet driver, see “The .ENET
  5506. Driver” earlier in this chapter.
  5507.  
  5508. _______________________________________________________________________________
  5509.  
  5510. æKY Attaching…and…Detaching…an…Ethernet…Protocol…Handler
  5511. æC »Attaching and Detaching an Ethernet Protocol Handler                 AppleTalk Manager
  5512. _______________________________________________________________________________
  5513.  
  5514. The functions in this section allow you to attach a protocol handler to the
  5515. .ENET driver, to specify which protocol handler the .ENET driver is to use for
  5516. each protocol type, and to detach a protocol handler that you previously
  5517. attached. The section “Using Your Own Ethernet Protocol Handler to Read Data”
  5518. earlier in this chapter, describes how to write and use Ethernet protocol
  5519. handlers.
  5520.  
  5521. FUNCTION EAttachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5522.  
  5523. Parameter block
  5524.   ¨  16  ioResult  word  result code 
  5525.   Æ  26  csCode  word  always EAttachPH
  5526.   Æ  28  EProtType  word  Ethernet protocol type
  5527.   Æ  30  EPointer  pointer  pointer to protocol handler
  5528.  
  5529. The EAttachPH function serves two purposes: You can use it to attach to the 
  5530. .ENET driver your own protocol handler for a specific protocol type; or you can
  5531. use it to specify that the .ENET driver should use the default protocol handler
  5532. for a particular protocol type. If you attach your own protocol handler, the 
  5533. .ENET driver calls that protocol handler each time it receives a packet with the
  5534. protocol type you specified. If you specify that the .ENET driver should use the
  5535. default protocol handler, then you can use the ERead command to read packets
  5536. with that protocol type. 
  5537.  
  5538. The ioResult parameter returns the result of the function; if you call the
  5539. function asynchronously, the function sets this field to 1 as soon as it begins
  5540. execution, and changes the field to the actual result code when it completes
  5541. execution. The csCode parameter is a routine selector that is set automatically
  5542. for you by the MPW interface; it is always equal to EAttachPH for this function.
  5543. You specify the protocol type in the EProtType parameter and provide a pointer
  5544. to the protocol handler in the EPointer parameter. If you specify NIL for the
  5545. EPointer parameter, then the .ENET driver uses the default protocol handler for
  5546. that protocol type. Specify 0 for the EProtType parameter to attach a protocol
  5547. handler for the IEEE 802.3 protocol, which uses protocol types 0 through $5DC.
  5548.  
  5549. Note:  In addition to using the EAttachPH function to install a protocol handler
  5550. for an Ethernet protocol type, you can use the L802Attach function to install a
  5551. protocol handler for an 802.2 protocol type. In the case of an 802.2 protocol
  5552. packet, the .ENET driver passes the packet to the LAP Manager 802.2 protocol
  5553. handler. If the packet has the protocol type you specified with the L802Attach
  5554. function, the 802.2 protocol handler passes the packet on to your protocol
  5555. handler. See “The LAP Manager 802.2 Protocol” earlier in this chapter, for more
  5556. information about IEEE 802.2 protocols.
  5557.  
  5558. Result codes
  5559. noErr         0  no error
  5560. LAPProtErr  –94  protocol handler is already attached or node’s protocol 
  5561.                  table is full
  5562.  
  5563. FUNCTION EDetachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5564.  
  5565. Parameter block
  5566.   ¨  16  ioResult  word  result code 
  5567.   Æ  26  csCode  word  always EDetachPH
  5568.   Æ  28  EProtType  word  Ethernet protocol type
  5569.  
  5570. The EDetachPH function detaches a protocol handler from the .ENET driver. Once
  5571. you have removed a protocol type from the node’s protocol table with this
  5572. command, the .ENET driver no longer delivers packets with that protocol type.
  5573. You specify the protocol type in the EProtType parameter.
  5574.  
  5575. The ioResult parameter returns the result of the function; if you call the
  5576. function asynchronously, the function sets this field to 1 as soon as it begins
  5577. execution, and changes the field to the actual result code when it completes
  5578. execution. The csCode parameter is a routine selector that is set automatically
  5579. for you by the MPW interface; it is always equal to EAttachPH for this function.
  5580.  
  5581. Result codes
  5582. noErr         0  no error
  5583. LAPProtErr  –94  no protocol handler attached
  5584. _______________________________________________________________________________
  5585.  
  5586. æKY Writing…and…Reading…Packets…Using…the…Default…Protocol…Handler
  5587. æC »Writing and Reading Packets Using the Default Protocol Handler       AppleTalk Manager
  5588. _______________________________________________________________________________
  5589.  
  5590. FUNCTION EWrite (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5591.  
  5592. Parameter block
  5593.   ¨  16  ioResult  word  result code 
  5594.   Æ  26  csCode  word  always EWrite
  5595.   Æ  30  EPointer  pointer  pointer to write-data structure
  5596.  
  5597. The EWrite function uses the .ENET driver to send a data packet over Ethernet.
  5598. You must first prepare a write-data structure, which specifies the destination
  5599. address and the protocol type and contains the data that you want to send. You
  5600. place a pointer to the write-data structure in the EPointer parameter. If you
  5601. want to send a packet larger than 768 bytes, you must first call the ESetGeneral
  5602. command to put the .ENET driver in general transmission mode. If the size of the
  5603. packet you provide is less than 60 bytes, the driver adds pad bytes to the
  5604. packet. Write-data structures are described in “Using a Write-Data Structure to
  5605. Transmit Ethernet Data” earlier in this chapter.
  5606.  
  5607. The ioResult parameter returns the result of the function; if you call the
  5608. function asynchronously, the function sets this field to 1 as soon as it begins
  5609. execution, and changes the field to the actual result code when it completes
  5610. execution. The csCode parameter is a routine selector that is set automatically
  5611. for you by the MPW interface; it is always equal to EWrite for this function.
  5612.  
  5613. Result codes
  5614. noErr            0  no error
  5615. elenErr             packet too large or first write-data-structure entry did
  5616.                     not contain the full 14-byte header
  5617. excessCollsns  –95  hardware error
  5618.  
  5619. FUNCTION ERead (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5620.  
  5621. Parameter block
  5622.   ¨  16  ioResult  word  result code 
  5623.   Æ  26  csCode  word  always ERead
  5624.   Æ  28  EProtType  word  Ethernet protocol type
  5625.   Æ  30  EPointer  pointer  pointer to data buffer
  5626.   Æ  34  EBuffSize  word  size of data buffer
  5627.   ¨  36  EDataSize  word  number of bytes read
  5628.  
  5629. The ERead function uses the default protocol handler to read a data packet and
  5630. place it in a data buffer. You can use the ERead function to read packets of a
  5631. particular protocol type only after you have used the EAttachPH function to
  5632. specify a NIL pointer to the protocol handler for that protocol type.
  5633.  
  5634. The ioResult parameter returns the result of the function; if you call the
  5635. function asynchronously, the function sets this field to 1 as soon as it begins
  5636. execution, and changes the field to the actual result code when it completes
  5637. execution. The csCode parameter is the routine selector, automatically set by
  5638. the MPW interface. It is always ERead for this function. The ccbRefNum parameter
  5639. is the connection control block reference number that was returned by the
  5640. dspInit command. 
  5641.  
  5642. The EProtType parameter specifies the protocol type of the packet you want to
  5643. read. The EPointer parameter is a pointer to the data buffer into which you want
  5644. to read data, and the EBuffSize parameter indicates the size of the data buffer.
  5645. If you are expecting EtherTalk data packets, the buffer should be at least 617
  5646. bytes in size; if you are expecting general Ethernet data packets, the buffer
  5647. should be at least 1514 bytes in size. 
  5648.  
  5649. The ERead function places the entire packet—including the packet header—into
  5650. your buffer. The function returns in the EDataSize parameter the number of bytes
  5651. actually read. If the packet is larger than the data buffer, the ERead function
  5652. places as much of the packet as will fit into the buffer and returns the
  5653. buf2SmallErr result code.
  5654.  
  5655. Call the ERead function asynchronously to await the next data packet. When the
  5656. .ENET driver receives the data packet, it completes execution of the ERead
  5657. function and calls your completion routine. If the .ENET driver receives a data
  5658. packet with a protocol type for which you specified the default protocol
  5659. handler, but there is no ERead command pending, the driver discards the data
  5660. packet.
  5661.  
  5662. You can have several asynchronous calls to the ERead function pending execution
  5663. simultaneously, as long as you use a different parameter block for each call.
  5664.  
  5665. Result codes
  5666. noErr             0  no error
  5667. LAPProtErr      –94  protocol not attached or protocol handler pointer was not 0
  5668. buf2SmallErr  –3101  packet too large for buffer; partial data returned
  5669. reqAborted    –1105  ERdCancel function called for this ERead
  5670.  
  5671. FUNCTION ERdCancel (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5672.  
  5673. Parameter block
  5674.   ¨  16  ioResult  word  result code 
  5675.   Æ  26  csCode  word  always ERdCancel
  5676.   Æ  30  EPointer  pointer  pointer to ERead parameter block
  5677.  
  5678. The ERdCancel function cancels execution of a specific call to the ERead
  5679. function. You must have called the ERead function asynchronously to use the
  5680. ERdCancel function. You specify in the EPointer parameter a pointer to the
  5681. parameter block that you used when you called the ERead function. 
  5682. The ioResult parameter returns the result of the function; if you call the
  5683. function asynchronously, the function sets this field to 1 as soon as it begins
  5684. execution, and changes the field to the actual result code when it completes
  5685. execution. The csCode parameter is the routine selector, automatically set by
  5686. the MPW interface. It is always ERdCancel for this function. The ccbRefNum
  5687. parameter is the connection control block reference number that was returned by
  5688. the dspInit command. 
  5689.  
  5690. Result codes
  5691. noErr           0  no error
  5692. CBNotFound  –1102  ERead not active
  5693.  
  5694. FUNCTION EGetInfo (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5695.  
  5696. Parameter block
  5697.   ¨  16  ioResult  word  result code 
  5698.   Æ  26  csCode  word  always EGetInfo
  5699.   Æ  30  EPointer  pointer  pointer to buffer
  5700.   Æ  34  EBuffSize  word  size of buffer
  5701.  
  5702. The EGetInfo function returns information about the .ENET driver. Before calling
  5703. this function, you must allocate a data buffer of at least 18 bytes. Put a
  5704. pointer to the buffer in the EPointer parameter and the size of the buffer in
  5705. the EBuffSize parameter.
  5706.  
  5707. The EGetInfo function places the following information in the data buffer:
  5708.  
  5709. Bytes  Information
  5710.  
  5711. 1–6    Ethernet address of the node on which the driver is installed
  5712. 7–10   Number of times the receive buffer has overflowed
  5713. 11–14  Number of data transmission operations that have timed out 
  5714. 15–18  Number of packets received that contain an incorrect address
  5715.  
  5716. The ioResult parameter returns the result of the function; if you call the
  5717. function asynchronously, the function sets this field to 1 as soon as it begins
  5718. execution, and changes the field to the actual result code when it completes
  5719. execution. The csCode parameter is the routine selector, automatically set by
  5720. the MPW interface. It is always EGetInfo for this function. The ccbRefNum
  5721. parameter is the connection control block reference number that was returned by
  5722. the dspInit command. 
  5723.  
  5724. Result code
  5725. noErr  0  no error
  5726.  
  5727. FUNCTION ESetGeneral (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5728.  
  5729. Parameter block
  5730.   ¨  16  ioResult  word  result code 
  5731.   Æ  26  csCode  word  always ESetGeneral
  5732.  
  5733. The ESetGeneral function switches the .ENET driver from limited-transmission
  5734. mode to general-transmission mode. In limited-transmission mode, the .ENET
  5735. driver allocates a write-data buffer of 768 bytes. This buffer size is more than
  5736. sufficient to hold an EtherTalk data packet, which can be no larger than 617
  5737. bytes. In general-transmission mode, the .ENET driver can transmit an Ethernet
  5738. data packet of up to 1514 bytes.
  5739.  
  5740. The ioResult parameter returns the result of the function; if you call the
  5741. function asynchronously, the function sets this field to 1 as soon as it begins
  5742. execution, and changes the field to the actual result code when it completes
  5743. execution. The csCode parameter is the routine selector, automatically set by
  5744. the MPW interface. It is always ESetGeneral for this function. The ccbRefNum
  5745. parameter is the connection control block reference number that was returned by
  5746. the dspInit command. 
  5747.  
  5748. There is no command to switch the .ENET driver from general-transmission mode to
  5749. limited-transmission mode. To switch back to limited-transmission mode, you have
  5750. to reset the driver by restarting the computer.
  5751.  
  5752. Result codes
  5753. noErr  0  no error
  5754. _______________________________________________________________________________
  5755.  
  5756. æKY Adding…and…Removing…Ethernet…Multicast…Addresses
  5757. æC »Adding and Removing Ethernet Multicast Addresses                     AppleTalk Manager
  5758. _______________________________________________________________________________
  5759.  
  5760. FUNCTION EAddMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5761.  
  5762. Parameter block
  5763.   ¨  16  ioResult  word  result code 
  5764.   Æ  26  csCode  word  always EAddMulti
  5765.   Æ  28  EMultiAddr  6 bytes  multicast address
  5766.  
  5767. The EAddMulti function adds a multicast address to the node on which the .ENET
  5768. driver is running. A multicast address is an Ethernet address for which the node
  5769. accepts packets just as it does to its permanently assigned Ethernet hardware
  5770. address. In a muticast address, the low-order bit of the high-order byte is set
  5771. to 1. Each node can have any number of multicast addresses, and any number of
  5772. nodes can have the same multicast address. The purpose of a multicast address is
  5773. to allow a group of Ethernet nodes to receive the same transmission
  5774. simultaneously, in a fashion similar to the AppleTalk broadcast service.
  5775.  
  5776. You must provide (in the EMultiAddr parameter) the multicast address that you
  5777. want to use. Each time a client of the .ENET driver calls the EAddMulti function
  5778. for a particular multicast address, the driver increments a counter for that
  5779. multicast address. Each time a client of the .ENET driver calls the EDelMulti
  5780. function, the driver decrements the counter for that address. As long as the
  5781. count for a multicast address is equal to or greater than 1, the .ENET driver
  5782. accepts packets directed to that multicast address. If any client of the .ENET
  5783. driver in the node has called the EAddMulti function for a particular multicast
  5784. address, therefore, the driver receives packets delivered to that address.
  5785.  
  5786. The ioResult parameter returns the result of the function; if you call the
  5787. function asynchronously, the function sets this field to 1 as soon as it begins
  5788. execution, and changes the field to the actual result code when it completes
  5789. execution. The csCode parameter is the routine selector, automatically set by
  5790. the MPW interface. It is always EAddMulti for this function. The ccbRefNum
  5791. parameter is the connection control block reference number that was returned by
  5792. the dspInit command. 
  5793.  
  5794. Result codes
  5795. noErr        0  no error
  5796. eMultiErr    invalid address or table is full 
  5797.  
  5798. FUNCTION EDelMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5799.  
  5800. Parameter block
  5801.   ¨  16  ioResult  word  result code 
  5802.   Æ  26  csCode  word  always EDelMulti
  5803.   Æ  28  EMultiAddr  6 bytes  multicast address
  5804.  
  5805. The EDelMulti function decrements the counter kept by the .ENET driver for a
  5806. particular multicast address. Each time a client of the .ENET driver calls the
  5807. EAddMulti function, the driver increments a counter for the multicast address
  5808. specified by the EMultiAddr parameter. Each time a client of the .ENET driver
  5809. calls the EDelMulti function, the driver decrements the counter for the address
  5810. specified by the EMultiAddr parameter. As long as the count for a multicast
  5811. address is equal to or greater than 1, the .ENET driver accepts packets directed
  5812. to that multicast address. When the count for an address equals 0, the driver
  5813. removes that address from the list of multicast addresses that it accepts.
  5814.  
  5815. Note:  Because more than one client of the .ENET driver might be using a
  5816. particular multicast address, you should call the EDelMulti function only once
  5817. for each time you called the EAddMulti function.
  5818.  
  5819. The ioResult parameter returns the result of the function; if you call the
  5820. function asynchronously, the function sets this field to 1 as soon as it begins
  5821. execution, and changes the field to the actual result code when it completes
  5822. execution. The csCode parameter is the routine selector, automatically set by
  5823. the MPW interface. It is always EDelMulti for this function. The ccbRefNum
  5824. parameter is the connection control block reference number that was returned by
  5825. the dspInit command. 
  5826.  
  5827. Result codes
  5828. noErr      0  no error
  5829. eMultiErr     address not found
  5830. _______________________________________________________________________________
  5831.  
  5832. æKY Summary…of…the…AppleTalk…Manager…Vol…VI
  5833. æC »SUMMARY OF THE APPLETALK MANAGER                                     AppleTalk Manager
  5834. _______________________________________________________________________________
  5835.  
  5836. The following cards summarize the constants, data types, and routines for the
  5837. AppleTalk Manager.
  5838. _______________________________________________________________________________
  5839.  
  5840. æKY AppleTalk…Constants
  5841. æC »Constants                                                            AppleTalk Manager
  5842. _______________________________________________________________________________
  5843.  
  5844. CONST
  5845. {csCodes for new .XPP driver routines}
  5846.   xCall = 246;
  5847.  
  5848. {xppSubCodes}
  5849.   getLocalZones = 5;
  5850.   getZoneList   = 6;
  5851.   getMyZone     = 7;
  5852.  
  5853.  
  5854. {driver control csCodes}
  5855. dspInit       = 255;  {create a new connection end}
  5856. dspRemove     = 254;  {remove a connection end}
  5857. dspOpen       = 253;  {open a connection}
  5858. dspClose      = 252;  {close a connection}
  5859. dspCLInit     = 251;  {create a connection listener}
  5860. dspCLRemove   = 250;  {remove a connection listener}
  5861. dspCLListen   = 249;  {post a listener request}
  5862. dspCLDeny     = 248;  {deny an open connection request}
  5863. dspStatus     = 247;  {get status of connection end}
  5864. dspRead       = 246;  {read data from the connection}
  5865. dspWrite      = 245;  {write data on the connection}
  5866. dspAttention  = 244;  {send an attention message}
  5867. dspOptions    = 243;  {set connection end options}
  5868. dspReset      = 242;  {forward reset the connection}
  5869. dspNewCID     = 241;  {generate a cid for a connection end}
  5870.  
  5871. {connection opening modes}
  5872. ocRequest    = 1;  {request a connection with remote}
  5873. ocPassive    = 2;  {wait for a connection request from remote}
  5874. ocAccept     = 3;  {accept request as delivered by listener}
  5875. ocEstablish  = 4;  {consider connection to be open}
  5876.  
  5877. {connection end states}
  5878. sListening  = 1;  {for connection listeners}
  5879. sPassive    = 2;  {waiting for a connection request from remote}
  5880. sOpening    = 3;  {requesting a connection with remote}
  5881. sOpen       = 4;  {connection is open}
  5882. sClosing    = 5;  {connection is being torn down}
  5883. sClosed     = 6;  {connection end state is closed}
  5884.  
  5885. {client event flags}
  5886. eClosed     = $80;  {received connection closed advice}
  5887. eTearDown   = $40;  {closed due to broken connection}
  5888. eAttention  = $20;  {received attention message}
  5889. eFwdReset   = $10;  {received forward reset advice}
  5890.  
  5891. {miscellaneous constants}
  5892. attnBufSize      = 570;  {size of client attention buffer}
  5893. minDSPQueueSize  = 100;  {Minimum size of receive or send Queue}
  5894. _______________________________________________________________________________
  5895.  
  5896. æKY AppleTalk…Data…Types
  5897. æC »Data Types                                                           AppleTalk Manager
  5898. _______________________________________________________________________________
  5899.  
  5900. TYPE ATQentry = RECORD
  5901.    qLink:     ATQentryPtr;  {next queue entry}
  5902.    qType:     INTEGER;      {unused}
  5903.    CallAddr:  ProcPtr       {pointer to your routine}
  5904. END;
  5905.  
  5906. ATQentryptr = ^ATQentry;
  5907.  
  5908. TPCCB = ^TRCCB;
  5909.  
  5910. TRCCB = PACKED RECORD
  5911.    ccbLink:        TPCCB;      {link to next CCB}
  5912.    refNum:         INTEGER;    {user reference number}
  5913.    state:          INTEGER;    {state of the connection end}
  5914.    userFlags:      Byte;       {user flags for connection}
  5915.    localSocket:    Byte;       {local socket number}
  5916.    remoteAddress:  AddrBlock;  {remote end internet address}
  5917.    attnCode:       INTEGER;    {attention code received}
  5918.    attnSize:       INTEGER;    {size of attention data}
  5919.    attnPtr:        Ptr;        {pointer to attention data}
  5920.    reserved:       PACKED ARRAY [1..220] OF Byte {reserved for use by ADSP}
  5921. END;
  5922.  
  5923. AddrBlock = PACKED RECORD
  5924.   aNet:     INTEGER;  {network number}
  5925.   aNode:    Byte;     {node ID}
  5926.   aSocket:  Byte      {socket number}
  5927. END;
  5928.  
  5929. DSPParamBlock = PACKED RECORD
  5930.   qLink:          QElemPtr;   {next queue entry}
  5931.   qType:          INTEGER;    {queue type}
  5932.   ioTrap:         INTEGER;    {routine trap}
  5933.   ioCmdAddr:      Ptr;        {routine address}
  5934.   ioCompletion:   ProcPtr;    {completion routine}
  5935.   ioResult:       OSErr;      {result code}
  5936.   ioNamePtr:      StringPtr;  {used only for Open routine}
  5937.   ioVRefNum:      INTEGER;    {volume reference number}
  5938.   ioCRefNum:      INTEGER;    {driver reference number}
  5939.   csCode:         INTEGER;    {primary command code}
  5940.   qStatus:        LONGINT;    {reserved for ADSP}
  5941.   ccbRefNum:      INTEGER;    {CCB reference number}
  5942.   CASE INTEGER OF
  5943.    dspInit,
  5944.    dspCLInit:
  5945.    (
  5946.     ccbPtr:       TPCCB;      {pointer to CCB}
  5947.     userRoutine:  ProcPtr;    {pointer to user routine}
  5948.     sendQSize:    INTEGER;    {size of send queue}
  5949.     sendQueue:    Ptr;        {pointer to send queue}
  5950.     recvQSize:    INTEGER;    {size of receive queue}
  5951.     recvQueue:    Ptr;        {pointer to receive queue}
  5952.     attnPtr:      Ptr;        {pointer to attention-message buffer}
  5953.     localSocket:  Byte;       {local socket number}
  5954.    ); 
  5955.  
  5956.   dspOpen,
  5957.   dspCLListen,
  5958.   dspCLDeny:
  5959.    (
  5960.     localCID:       INTEGER;    {local connection ID}
  5961.     remoteCID:      INTEGER;    {remote connection ID}
  5962.     remoteAddress:  AddrBlock;  {remote internet address}
  5963.     filterAddress:  AddrBlock;  {address filter}
  5964.     sendSeq:        LONGINT;    {send sequence number}
  5965.     sendWindow:     INTEGER;    {size of remote buffer}
  5966.     recvSeq:       LONGINT;   {receive sequence number}
  5967.    attnSendSeq:   LONGINT;   {attention send seq number}
  5968.    attnRecvSeq:   LONGINT;   {attention receive seq num}
  5969.    ocMode:        Byte;      {connection opening mode}
  5970.     ocInterval:     Byte;       {interval bet open requests}
  5971.     ocMaximum:      Byte;       {retries of open conn req}
  5972.    );
  5973.  
  5974. dspClose,
  5975. dspRemove:
  5976. (
  5977.   abort:            Byte;       {abort send requests}
  5978. );
  5979.  
  5980. dspStatus:
  5981. (
  5982.   statusCCB:        TPCCB;      {pointer to CCB}
  5983.   sendQPending:     INTEGER;    {bytes waiting in send queue}
  5984.   sendQFree:        INTEGER;    {available send-queue buffer}
  5985.   recvQPending:     INTEGER;    {bytes in receive queue}
  5986.   recvQFree:        INTEGER;    {avail receive-queue buffer}
  5987. )
  5988.  
  5989. dspRead,
  5990. dspWrite:
  5991. (
  5992.   reqCount:  INTEGER;  {requested number of bytes}
  5993.   actCount:  INTEGER;  {actual number of bytes}
  5994.   dataPtr:   Ptr;      {pointer to data buffer}
  5995.   eom:       Byte;     {1 if end of message}
  5996.   flush:     Byte;     {1 to send data now}
  5997. )
  5998.  
  5999. dspAttention:
  6000. (
  6001.   attnCode:      INTEGER;  {client attention code}
  6002.   attnSize:      INTEGER;  {size of attention data}
  6003.   attnData:      Ptr;   {pointer to attention data}
  6004.   attnInterval:  Byte;  {reserved}
  6005. )
  6006.  
  6007. dspOptions:
  6008. (
  6009.   sendBlocking:  INTEGER;  {send-blocking threshold}
  6010.   sendTimer:      Byte;    {reserved}
  6011.   rtmtTimer:      Byte;    {reserved}
  6012.   badSeqMax:      Byte;    {retransmit advice threshold}
  6013.   useCheckSum:    Byte;    {DDP checksum for packets}
  6014. )
  6015.  
  6016. dspNewCID:
  6017. (
  6018.   newCID:  INTEGER;  {new connection ID}
  6019. )
  6020. END;
  6021.  
  6022. xCallParam = PACKED RECORD
  6023. qLink:   QElemPtr;  {next queue entry}
  6024. qType:       INTEGER;    {queue type}
  6025. ioTrap:       INTEGER;   {routine trap}
  6026. ioCmdAddr:    Ptr;       {routine address}
  6027. ioCompletion: ProcPtr;   {completion routine}
  6028. ioResult:     OsErr;     {result code}
  6029. ioNamePtr:    StringPtr; {used only for Open routine}
  6030. ioVRefNum:    INTEGER;   {volume reference number}
  6031. ioRefNum:     INTEGER;   {driver reference number}
  6032. csCode:       INTEGER;   {primary command code}
  6033. xppSubCode:   INTEGER;   {secondary command code}
  6034. xppTimeOut:   Byte;      {timeout period for .XPP}
  6035. xppRetry:     Byte;      {retry count}
  6036. filler:       INTEGER;   {reserved}
  6037. zipBuffPtr:   Ptr;       {returned zone names}
  6038. zipNumZones:  INTEGER;   {number of zones returned}
  6039. zipLastFlag:  Byte;      {nonzero when all zone names have been returned}
  6040. filler:       Byte;      {reserved}
  6041. zipInfoField: packed array[1..70] of Byte
  6042.       {reserved for use by .XPP}
  6043. END;
  6044.  
  6045. XCallParamPtr = ^XCallParam;
  6046. EParamBlock = PACKED RECORD
  6047. qLink:   QElemPtr;  {next queue entry}
  6048. qType:   INTEGER;  {queue type}
  6049. ioTrap:   INTEGER;  {routine trap}
  6050. ioCmdAddr:   Ptr;  {routine address}
  6051. ioCompletion:   ProcPtr;  {completion routine}
  6052. ioResult:   OsErr;  {result code}
  6053. ioNamePtr:   StringPtr;  {driver name}
  6054. ioVRefNum:   INTEGER;  {volume reference number}
  6055. ioCRefNum:   INTEGER;  {driver reference number}
  6056. csCode:   INTEGER;  {primary command code}
  6057.  
  6058. CASE INTEGER OF
  6059. EWrite,
  6060. EAttachPH,
  6061. EDetachPH,
  6062. ERead,
  6063. ERdCancel,
  6064. EGetInfo,
  6065. ESetGeneral:
  6066.  
  6067. (
  6068. EProtType:  INTEGER;  {Ethernet protocol type}
  6069. EPointer:  Ptr;  {pointer; use depends on }
  6070.       { function}
  6071. EBuffSize  INTEGER  {buffer size}
  6072. EDataSize  INTEGER  {number of bytes read}
  6073. );
  6074.  
  6075. EAddMulti,
  6076. EDelMulti:
  6077.  
  6078. (
  6079. EMultiAddr:  ?????;  {Multicast address}
  6080. );
  6081. END;
  6082. _______________________________________________________________________________
  6083.  
  6084. æKY AppleTalk…Routines
  6085. æC »Routines                                                             AppleTalk Manager
  6086. _______________________________________________________________________________
  6087.  
  6088. Getting Information About the .MPP Driver
  6089.  
  6090. FUNCTION PGetAppleTalkInfo (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  6091.  
  6092. Parameter block
  6093.   ¨  16  ioResult  word  result code 
  6094.   Æ  26  csCode  word  always PGetAppleTalkInfo
  6095.   Æ  28  version  word  version of function
  6096.   ¨  30  varsPtr  pointer  pointer to MPP globals
  6097.   ¨  34  dcePtr  pointer  pointer to DCE for .MPP
  6098.   ¨  38  portID  word  port number 
  6099.   ¨  40  configuration  long  configuration flags
  6100.   ¨  44  selfSend  word  nonzero if self-send is enabled
  6101.   ¨  46  netLo  word  low value of the network range
  6102.   ¨  48  netHi  word  high value of the network range
  6103.   ¨  50  ourAddr  long  local 24-bit AppleTalk address
  6104.   ¨  54  routerAddr  long  24-bit address of router
  6105.   ¨  58  numOfPHs  word  max number of protocol handlers
  6106.   ¨  60  numOfSkts  word  max number of static sockets
  6107.   ¨  62  numNBPEs  word  max concurrent NBP requests
  6108.   ¨  64  ntQueue  pointer  pointer to registered name queue
  6109.   ´  68  laLength  word  length in bytes of data link address
  6110.           (extended networks only)
  6111.   Æ  70  linkAddr  pointer  pointer to data link address buffer
  6112.           (extended networks only)
  6113.   Æ  74  zoneName  pointer  pointer to zone name buffer
  6114.  
  6115. Adding and Removing AppleTalk Transition Queue Entries
  6116.  
  6117. PROCEDURE LAPAddATQ (entryPtr: pointer);
  6118. PROCEDURE LAPRmvATQ (entryPtr: pointer);
  6119. PROCEDURE LAPGetATQ (VAR eqPtr: pointer);
  6120.  
  6121. Sending Messages to the AppleTalk Transition Queue
  6122.  
  6123. FUNCTION PATalkClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  6124.  
  6125. Parameter block
  6126.   Æ  26  csCode  word  always PATalkClosePrep
  6127.   Æ      appName  pointer  buffer for name of application that 
  6128.           denies request
  6129.  
  6130. FUNCTION PCancelATClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  6131.  
  6132. Parameter block
  6133.   Æ  26  csCode  word  always PCancelATClosePrep 
  6134.  
  6135. Attaching and Detaching 802.2 Protocol Handlers
  6136.  
  6137. FUNCTION L802Attach (Eref: word; handlerPtr: procptr; 
  6138.            ProtType: pointer) : OSErr;
  6139. FUNCTION L802Detach (Eref: word; ProtType: pointer) : OSErr;
  6140.  
  6141. Canceling Asynchronous Calls to the ATPKillAllGetReq Function 
  6142.  
  6143. FUNCTION ATPKillAllGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  6144.  
  6145. Parameter block
  6146.   Æ  26  csCode  word  always ATPKillAllGetReq
  6147.   Æ  28  atpSocket  byte  socket for which to cancel all calls 
  6148.           to ATPGetRequest
  6149.  
  6150. Using the .XPP Driver to Obtain Zone Information
  6151.  
  6152. FUNCTION GetMyZone (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  6153.  
  6154. Parameter block
  6155.   ¨  16  ioResult  word  result code 
  6156.   Æ  26  csCode  word  routine selector; always xCall
  6157.   Æ  28  xppSubCode  word  routine selector; getMyZone
  6158.   Æ  30  xppTimeOut  byte  retry interval in seconds
  6159.   Æ  31  xppRetry  byte  retry count
  6160.   Æ  34  zipBuffPtr  long  pointer to data buffer
  6161.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  6162.  
  6163. FUNCTION GetLocalZones (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  6164.  
  6165. Parameter block
  6166.   ¨  16  ioResult  word  result code 
  6167.   Æ  26  csCode  word  routine selector; always xCall
  6168.   Æ  28  xppSubCode  word  routine selector; getLocalZones
  6169.   Æ  30  xppTimeOut  byte  retry interval in seconds
  6170.   Æ  31  xppRetry  byte  retry count
  6171.   Æ  34  zipBuffPtr  pointer  pointer to data buffer
  6172.   ¨  38  zipNumZones  word  number of names returned
  6173.   ¨  40  zipLastFlag  byte  nonzero if no more names
  6174.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  6175.  
  6176. FUNCTION GetZoneList (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  6177.  
  6178. Parameter block
  6179.   ¨  16  ioResult  word  result code 
  6180.   Æ  26  csCode  word  routine selector; always xCall
  6181.   Æ  28  xppSubCode  word  routine selector; getZoneList
  6182.   Æ  30  xppTimeOut  byte  retry interval in seconds
  6183.   Æ  31  xppRetry  byte  retry count
  6184.   Æ  34  zipBuffPtr  pointer  pointer to data buffer
  6185.   ¨  38  zipNumZones  word  number of names returned
  6186.   ¨  40  zipLastFlag  byte  nonzero if no more names
  6187.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  6188.  
  6189. Attaching and Detaching an Ethernet Protocol Handler
  6190.  
  6191. FUNCTION EAttachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6192.  
  6193. Parameter block
  6194.   ¨  16  ioResult  word  result code 
  6195.   Æ  26  csCode  word  always EAttachPH
  6196.   Æ  28  EProtType  word  Ethernet protocol type
  6197.   Æ  30  EPointer  pointer  pointer to protocol handler
  6198.  
  6199. FUNCTION EDetachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6200.  
  6201. Parameter block
  6202.   ¨  16  ioResult  word  result code 
  6203.   Æ  26  csCode  word  always EDetachPH
  6204.   Æ  28  EProtType  word  Ethernet protocol type
  6205.  
  6206. Writing and Reading Ethernet Packets Using the Default Protocol Handler
  6207.  
  6208. FUNCTION EWrite (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6209.  
  6210. Parameter block
  6211.   ¨  16  ioResult  word  result code 
  6212.   Æ  26  csCode  word  always EWrite
  6213.   Æ  30  EPointer  pointer  pointer to write-data structure
  6214.  
  6215. FUNCTION ERead (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6216.  
  6217. Parameter block
  6218.   ¨  16  ioResult  word  result code 
  6219.   Æ  26  csCode  word  always ERead
  6220.   Æ  28  EProtType  word  Ethernet protocol type
  6221.   Æ  30  EPointer  pointer  pointer to data buffer
  6222.   Æ  34  EBuffSize  word  size of data buffer
  6223.   ¨  36  EDataSize  word  number of bytes read
  6224.  
  6225. FUNCTION ERdCancel (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6226.  
  6227. Parameter block
  6228.   ¨  16  ioResult  word  result code 
  6229.   Æ  26  csCode  word  always ERdCancel
  6230.   Æ  30  EPointer  pointer  pointer to ERead parameter block
  6231.  
  6232. FUNCTION EGetInfo (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6233.  
  6234. Parameter block
  6235.   ¨  16  ioResult  word  result code 
  6236.   Æ  26  csCode  word  always EGetInfo
  6237.   Æ  30  EPointer  pointer  pointer to buffer
  6238.   Æ  34  EBuffSize  word  size of buffer
  6239.  
  6240. FUNCTION ESetGeneral (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6241.  
  6242. Parameter block
  6243.   ¨  16  ioResult  word  result code 
  6244.   Æ  26  csCode  word  always ESetGeneral
  6245.  
  6246. Adding and Removing Ethernet Multicast Addresses
  6247.  
  6248. FUNCTION EAddMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6249.  
  6250. Parameter block
  6251.   ¨  16  ioResult  word  result code 
  6252.   Æ  26  csCode  word  always EAddMulti
  6253.   Æ  28  EMultiAddr  6 bytes  multicast address
  6254.  
  6255. FUNCTION EDelMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6256.  
  6257. Parameter block
  6258.   ¨  16  ioResult  word  result code 
  6259.   Æ  26  csCode  word  always EDelMulti
  6260.   Æ  28  EMultiAddr  6 bytes  multicast address
  6261. _______________________________________________________________________________
  6262.  
  6263. æKY AppleTalk…Result…codes
  6264. æC »Result codes                                                         AppleTalk Manager
  6265. _______________________________________________________________________________
  6266.  
  6267. eMultiErr                invalid address or table is full 
  6268. elenErr                  packet too large or first write-data-structure entry
  6269.                          did not contain the full 14-byte header
  6270. noErr                 0  no error
  6271. closeErr            –24  permission to close .MPP driver was denied
  6272. ddpSktErr           –91  error opening socket
  6273. noBridgeErr         –93  no router is available
  6274. LAPProtErr          –94  protocol handler is already attached or node’s protocol
  6275.  
  6276.                          table is full
  6277. LAPProtErr          –94  no protocol handler attached
  6278. LAPProtErr          –94  protocol not attached or protocol handler pointer was
  6279.                          not 0
  6280. excessCollsns       –95  hardware error
  6281. reqFailed         –1096  request to contact router failed; retry count exceeded 
  6282. cbNotFound        –1102  control block not found; no pending asynchronous calls
  6283. CBNotFound        –1102  ERead not active
  6284. reqAborted        –1105  ERdCancel function called for this ERead
  6285. errDSPQueueSize   –1274  send or receive queue is too small
  6286. errFwdReset       –1275  read terminated by forward reset
  6287. errAttention      –1276  attention message too long
  6288. errOpening        –1277  attempt to open connection failed
  6289. errState          –1278  bad connection state for this operation
  6290. errAborted        –1279  request aborted by dspRemove or dspClose command
  6291. errRefNum         –1280  bad connection reference number
  6292. buf2SmallErr      –3101  packet too large for buffer; partial data returned
  6293. _______________________________________________________________________________
  6294.  
  6295. æKY Assembly-language…Information…for…AppleTalk
  6296. æC »Assembly-language Information                                        AppleTalk Manager
  6297. _______________________________________________________________________________
  6298.  
  6299. Constants
  6300.  
  6301. mainVersion   EQU  1
  6302. subVersion    EQU  1
  6303. ;client control codes
  6304. dspInit       EQU  255  ;create a new connection end
  6305. dspRemove     EQU  254  ;remove a connection end
  6306. dspOpen       EQU  253  ;open a connection
  6307. dspClose      EQU  252  ;close a connection
  6308. dspCLInit     EQU  251  ;create a connection listener
  6309. dspCLRemove   EQU  250  ;remove a connection listener
  6310. dspCLListen   EQU  249  ;post a listener request
  6311. dspCLDeny     EQU  248  ;deny an open connection request
  6312. dspStatus     EQU  247  ;get status of connection end
  6313. dspRead       EQU  246  ;read data from the connection
  6314. dspWrite      EQU  245  ;write data on the connection
  6315. dspAttention  EQU  244  ;send an attention message
  6316. dspOptions    EQU  243  ;set connection end options
  6317. dspReset      EQU  242  ;forward reset the connection
  6318. dspNewCID     EQU  241  ;generate a cid for a connection end
  6319. ;open connection modes
  6320. ocRequest     EQU  1  ;request a connection with remote
  6321. ocPassive     EQU  2  ;wait for a connection request from remote
  6322. ocAccept      EQU  3  ;accept request as delivered by listener
  6323. ocEstablish   EQU  4  ;consider connection to be open
  6324. ;connection states
  6325. sListening    EQU  1  ;for connection listeners
  6326. sPassive      EQU  2  ;waiting for a connection request from remote
  6327. sOpening      EQU  3  ;requesting a connection with remote
  6328. sOpen         EQU  4  ;connection is open
  6329. sClosing      EQU  5  ;connection is being torn down
  6330. sClosed       EQU  6  ;connection end state is closed
  6331. ;client event flags (bit-mask)
  6332. eClosed       EQU  $80  ;received connection closed advice
  6333. eTearDown     EQU  $40  ;closed due to broken connection
  6334. eAttention    EQU  $20  ;received attention message
  6335. eFwdReset     EQU  $10  ;received forward reset advice
  6336. ;miscellaneous equates
  6337. attnBufSize      EQU  570  ;size of client attention message
  6338. minDSPQueueSize  EQU  100  ;minimum size for both receive and send queues
  6339. ;connection control block equates & size
  6340. ccbLink          EQU  0                ;link to next ccb
  6341. refNum           EQU  ccbLink+4        ;user reference number
  6342. state            EQU  refNum+2         ;state of the connection end
  6343. userFlags        EQU  state+2          ;flags for unsolicited connection events
  6344. localSocket      EQU  userFlags+1      ;socket number of this connection end
  6345. remoteAddress    EQU  localSocket+1    ;internet address of remote end
  6346. attnCode         EQU  remoteAddress+4  ;attention code received
  6347. attnSize         EQU  attnCode+2       ;size of received attention data
  6348. attnPtr          EQU  attnSize+2       ;ptr to received attention data
  6349. ccbSize          EQU  attnPtr+224      ;total byte size of ccb
  6350. ;adsp queue element equates & size
  6351. csQStatus    EQU  CSParam  ;adsp internal use
  6352. csCCBRef     EQU  csQStatus+4  ;refnum of ccb
  6353. ;dspInit, dspCLInit
  6354. csCCBPtr     EQU  csCCBRef+2     ;pointer to connection control block
  6355. csUserRtn    EQU  csCCBPtr+4     ;client routine to call on event
  6356. csSendQSize  EQU  csUserRtn+4    ;size of send queue (0..64K bytes)
  6357. csSendQueue  EQU  csSendQSize+2  ;client passed send queue buffer
  6358. csRecvQSize  EQU  csSendQueue+4  ;size of receive queue (0..64 KBb)
  6359. csRecvQueue  EQU  csRecvQSize+2  ;client passed receive queue buffer
  6360. csAttnPtr    EQU  csRecvQueue+4  ;client passed receive attention buffer
  6361. csLocSkt     EQU  csAttnPtr+4    ;local socket number
  6362. ;dspOpen, dspCLListen, dspCLDeny
  6363. csLocCID       EQU  csCCBRef+2    ;local connection id
  6364. csRemCID       EQU  csLocCID+2    ;remote connection id
  6365. csRemAddr      EQU  csRemCID+2    ;address of remote end
  6366. csFltrAddr     EQU  csRemAddr+4   ;address filter
  6367. csSendSeq      EQU  csFltrAddr+4  ;local send sequence number
  6368. csSendWdw      EQU  csSendSeq+4   ;send window size
  6369. csRecvSeq      EQU  csSendWdw+2   ;receive sequence number
  6370. csAttnSendSeq  EQU  csRecvSeq+4   ;attention send sequence number
  6371. csAttnRecvSeq  EQU  csAttnSendSeq+4  ;attention receive sequence number
  6372. csOCMode       EQU  csAttnRecvSeq+4  ;open connection mode
  6373. csOCInterval   EQU  csOCMode+1       ;open connection request retry interval
  6374. csOCMaximum    EQU  csOCInterval+1   ;open connection request retry maximum
  6375. ;dspClose, dspRemove
  6376. csAbort      EQU  csCCBRef+2     ;abort connection immediately if non-zero
  6377. ;dspStatus
  6378. csSQPending  EQU  csCCBPtr+4     ;pending bytes in send queue
  6379. csSQFree     EQU  csSQPending+2  ;available buffer space in send queue
  6380. csRQPending  EQU  csSQFree+2     ;pending bytes in receive queue
  6381. csRQFree     EQU  csRQPending+2  ;available buffer space in receive queue
  6382. ;dspRead, dspWrite
  6383. csReqCount      EQU  csCCBRef+2    ;requested number of bytes
  6384. csActCount      EQU  csReqCount+2  ;actual number of bytes
  6385. csDataPtr       EQU  csActCount+2  ;pointer to data buffer
  6386. csEOM           EQU  csDataPtr+4   ;indicates logical end of message
  6387. csFlush         EQU  csEOM+1       ;send data now dspAttention
  6388. csAttnCode      EQU  csCCBRef+2    ;client attention code
  6389. csAttnSize      EQU  csAttnCode+2  ;size of attention data
  6390. csAttnData      EQU  csAttnSize+2  ;pointer to attention data
  6391. csAttnInterval  EQU  csAttnData+4  ;retransmit timer in 10-tick intervals
  6392. ;dspOptions
  6393. csSendBlocking  EQU  csCCBRef+2        ;quantum for data packets
  6394. csSendTimer     EQU  csSendBlocking+2  ;send timer in 10-tick intervals
  6395. csRtmtTimer     EQU  csSendTimer+1     ;retransmit timer in 10-tick intervals
  6396. csBadSeqMax     EQU  csRtmtTimer+1     ;threshold for sending retransmit advice
  6397. csUseCheckSum   EQU  csBadSeqMax+1     ;use ddp packet checksum dspNewCID
  6398. csNewCID        EQU  csCCBRef+2        ;new connection id returned
  6399. dspPBSize       EQU  68                ;byte size of largest DSP param block
  6400. _______________________________________________________________________________
  6401.  
  6402.  
  6403. æKY About…The…AppleTalkManager…Chapter
  6404. æC »ABOUT THIS CHAPTER                                       AppleTalkManager
  6405. _______________________________________________________________________________
  6406.  
  6407. The AppleTalk Manager is an interface to a pair of RAM device drivers that allow
  6408. Macintosh programs to send and receive information via an AppleTalk network. This
  6409. chapter describes the AppleTalk Manager in detail.
  6410.  
  6411. The AppleTalk Manager has been enhanced through the implementation of new protocols
  6412. and an increase in the functionality of the existing interface.
  6413.  
  6414. Reader’s guide:  The AppleTalk Manager provides services that allow Macintosh
  6415.                  programs to interact with clients in devices connected to an
  6416.                  AppleTalk network.  Hence you need the information in this
  6417.                  chapter only if your application uses AppleTalk.
  6418.  
  6419. The following is a brief summary of the changes that have been made to the AppleTalk
  6420. Manager interface.
  6421.  
  6422.   •  New parameter block–style Pascal calls have been added for the entire
  6423.      AppleTalk Manager.  These new calls give the application programmer
  6424.      better control of AppleTalk operation within an application.
  6425.   •  At open time, the .MPP driver can be told to pick a node number in
  6426.      the server range.  This is a more time consuming but more thorough
  6427.      operation than is selecting a node number in the workstation range,
  6428.      and it is required for devices acting as servers.
  6429.   •  Multiple concurrent NBP requests are now supported (just as multiple
  6430.      concurrent ATP requests have been supported).  The KillNBP command
  6431.      has been implemented to abort an outstanding NBP request.
  6432.   •  ATP requests can now be sent through client-specified sockets, instead
  6433.      of having ATP pick the socket itself.
  6434.   •  The ability to send packets to one’s own node is supported (although
  6435.      this functionality is, in the default case, disabled).
  6436.   •  Two new ATP abort calls have been added: KillSendReq and KillGetReq.
  6437.      KillSendReq is functionally equivalent to RelTCB, although its
  6438.      arguments are different.  KillGetReq is a new call for aborting
  6439.      outstanding GetRequests.
  6440.   •  Additional machine-dependent resources have been added to support,
  6441.      for example, more dynamic sockets and more concurrent ATP requests. 
  6442.   •  A new protocol called the Echo Protocol (EP) is supported.
  6443.   •  A new driver, .XPP, has been added.  The .XPP driver implements the
  6444.      workstation side of the AppleTalk Session Protocol (ASP) and a small
  6445.      portion of the AppleTalk Filing Protocol.
  6446.  
  6447. To determine if your application is running on a machine that supports these enhanced
  6448. features, check the version number of the .MPP driver (at offset DCtlQueue+1 in the
  6449. Device Control Entry).  A version number of 48 (NCVersion) or greater indicates the
  6450. presence of the new drivers.
  6451.  
  6452. You should already be familiar with:
  6453.  
  6454.   •  events, as discussed in the Toolbox Event Manager chapter
  6455.   •  interrupts and the use of devices and device drivers, as described in
  6456.      the Device Manager chapter, if you want to write your own assembly-
  6457.      language additions to the AppleTalk Manager
  6458.   •  the Inside AppleTalk manual, if you want to understand AppleTalk
  6459.      protocols in detail
  6460.  
  6461. _______________________________________________________________________________
  6462.  
  6463.  
  6464. æKY AppleTalk…Protocols
  6465. æC »APPLETALK PROTOCOLS                                      AppleTalkManager
  6466. _______________________________________________________________________________
  6467.  
  6468. The AppleTalk Manager provides a variety of services that allow Macintosh programs to
  6469. interact with programs in devices connected to an AppleTalk network. This interaction,
  6470. achieved through the exchange of variable-length blocks of data (known as packets)
  6471. over AppleTalk, follows well-defined sets of rules known as protocols.
  6472.  
  6473. Although most programmers using AppleTalk needn’t understand the details of these
  6474. protocols, they should understand the information in this section—what the services
  6475. provided by the different protocols are, and how the protocols are interrelated.
  6476. Detailed information about AppleTalk protocols is available in Inside AppleTalk.
  6477.  
  6478. The AppleTalk system architecture consists of a number of protocols arranged in
  6479. layers. Each protocol in a specific layer provides services to higher-level layers
  6480. (known as the protocol’s clients) by building on the services provided by lower-level
  6481. layers. A Macintosh program can use services provided by any of the layers in order
  6482. to construct more sophisticated or more specialized services.  Figure 1 shows the
  6483. AppleTalk Protocols and their corresponding network layers.
  6484.  
  6485. The AppleTalk Manager contains the following protocols:
  6486.  
  6487.   •  AppleTalk Link Access Protocol
  6488.   •  Datagram Delivery Protocol
  6489.   •  Routing Table Maintenance Protocol
  6490.   •  Name-Binding Protocol
  6491.   •  AppleTalk Transaction Protocol
  6492.  
  6493. The following protocols have been added to the AppleTalk Manager:
  6494.  
  6495.   •  Echo Protocol
  6496.   •  AppleTalk Session Protocol (workstation side)
  6497.   •  AppleTalk Filing Protocol (small portion of the workstation side)
  6498.  
  6499. In Figure 1, the lines indicate the interaction between the protocols.  Notice that
  6500. like the Routing Table Maintenance Protocol, the Echo Protocol is not directly accessible
  6501. to Macintosh programs.
  6502.  
  6503. The details of these protocols are provided in Inside AppleTalk.
  6504.  
  6505. •••Refer to Figure 1.•••
  6506.  
  6507. Figure 1–AppleTalk Protocols and OSI Network Layers
  6508.  
  6509. Figure 2 illustrates the Macintosh AppleTalk Drivers and the layered structure of the
  6510. protocols which are accessible through each driver.  Note that the Routing Table
  6511. Maintenance Protocol isn’t directly accessible to Macintosh Programs.
  6512.  
  6513. •••Refer to Figure 2.•••
  6514.  
  6515. Figure 2–Macintosh AppleTalk Drivers
  6516.  
  6517. The AppleTalk Link Access Protocol (ALAP) provides the lowest-level services of the
  6518. AppleTalk system. Its main function is to control access to the AppleTalk network
  6519. among various competing devices. Each device connected to an AppleTalk network, known
  6520. as a node, is assigned an eight-bit node ID number that identifies the node. ALAP
  6521. ensures that each node on an AppleTalk network has a unique node ID, assigned dynamically
  6522. when the node is started up.
  6523.  
  6524. ALAP provides its clients with node-to-node delivery of data frames on a single
  6525. AppleTalk network. An ALAP frame is a variable-length packet of data preceded and
  6526. followed by control information referred to as the ALAP frame header and frame trailer,
  6527. respectively. The ALAP frame header includes the node IDs of the frame’s destination
  6528. and source nodes. The AppleTalk hardware uses the destination node ID to deliver the
  6529. frame. The frame’s source node ID allows a program in the receiving node to determine
  6530. the identity of the source. A sending node can ask ALAP to send a frame to all nodes
  6531. on the AppleTalk network; this broadcast service is obtained by specifying a destination
  6532. node ID of 255.
  6533.  
  6534. ALAP can have multiple clients in a single node. When a frame arrives at a node, ALAP
  6535. determines which client it should be delivered to by reading the frame’s ALAP protocol
  6536. type. The ALAP protocol type is an eight-bit quantity, contained in the frame’s
  6537. header, that identifies the ALAP client to whom the frame will be sent. ALAP calls
  6538. the client’s protocol handler, which is a software process in the node that reads in
  6539. and then services the frames. The protocol handlers for a node are listed in a protocol
  6540. handler table.
  6541.  
  6542. An ALAP frame trailer contains a 16-bit frame check sequence generated by the AppleTalk
  6543. hardware. The receiving node uses the frame check sequence to detect transmission
  6544. errors, and discards frames with errors. In effect, a frame with an error is “lost”
  6545. in the AppleTalk network, because ALAP doesn’t attempt to recover from errors by
  6546. requesting the sending node to retransmit such frames. Thus ALAP is said to make a
  6547. “best effort” to deliver frames, without any guarantee of delivery.
  6548.  
  6549. An ALAP frame can contain up to 600 bytes of client data. The first two bytes must be
  6550. an integer equal to the length of the client data (including the length bytes themselves).
  6551.  
  6552. Datagram Delivery Protocol (DDP) provides the next-higher level protocol in the
  6553. AppleTalk architecture, managing socket-to-socket delivery of datagrams over AppleTalk
  6554. internets. DDP is an ALAP client, and uses the node-to-node delivery service provided
  6555. by ALAP to send and receive datagrams. Datagrams are packets of data transmitted by
  6556. DDP. A DDP datagram can contain up to 586 bytes of client data. Sockets are logical
  6557. entities within the nodes of a network; each socket within a given node has a unique
  6558. eight-bit socket number.
  6559.  
  6560. On a single AppleTalk network, a socket is uniquely identified by its AppleTalk
  6561. address—its socket number together with its node ID. To identify a socket in the
  6562. scope of an AppleTalk internet, the socket’s AppleTalk address and network number are
  6563. needed. Internets are formed by interconnecting AppleTalk networks via intelligent
  6564. nodes called bridges. A network number is a 16-bit number that uniquely identifies a
  6565. network in an internet. A socket’s AppleTalk address together with its network number
  6566. provide an internet-wide unique socket identifier called an internet address.
  6567.  
  6568. Sockets are owned by socket clients, which typically are software processes in the
  6569. node. Socket clients include code called the socket listener, which receives and
  6570. services datagrams addressed to that socket. Socket clients must open a socket before
  6571. datagrams can be sent or received through it. Each node contains a socket table that
  6572. lists the listener for each open socket.
  6573.  
  6574. A datagram is sent from its source socket through a series of AppleTalk networks,
  6575. being passed on from bridge to bridge, until it reaches its destination network. The
  6576. ALAP in the destination network then delivers the datagram to the node containing the
  6577. destination socket. Within that node the datagram is received by ALAP calling the DDP
  6578. protocol handler, and by the DDP protocol handler in turn calling the destination
  6579. socket listener, which for most applications will be a higher-level protocol such as
  6580. the AppleTalk Transaction Protocol.
  6581.  
  6582. Bridges on AppleTalk internets use the Routing Table Maintenance Protocol (RTMP) to
  6583. maintain routing tables for routing datagrams through the internet. In addition,
  6584. nonbridge nodes use RTMP to determine the number of the network to which they’re
  6585. connected and the node ID of one bridge on their network. The RTMP code in nonbridge
  6586. nodes contains only a subset of RTMP (the RTMP stub), and is a DDP client owning
  6587. socket number 1 (the RTMP socket).
  6588.  
  6589. Socket clients are also known as network-visible entities, because they’re the primary
  6590. accessible entities on an internet. Network-visible entities can choose to identify
  6591. themselves by an entity name, an identifier of the form
  6592.  
  6593.   object:type@zone
  6594.  
  6595. Each of the three fields of this name is an alphanumeric string of up to 32 characters.
  6596. The object and type fields are arbitrary identifiers assigned by a socket client, to
  6597. provide itself with a name and type descriptor (for example, abs:Mailbox). The zone
  6598. field identifies the zone in which the socket client is located; a zone is an arbitrary
  6599. subset of AppleTalk networks in an internet. A socket client can identify itself by
  6600. as many different names as it chooses. These aliases are all treated as independent
  6601. identifiers for the same socket client.
  6602.  
  6603. The Name-Binding Protocol (NBP) maintains a names table in each node that contains
  6604. the name and internet address of each entity in that node. These name-address pairs
  6605. are called NBP tuples. The collection of names tables in an internet is known as the
  6606. names directory.
  6607.  
  6608. NBP allows its clients to add or delete their name-address tuples from the
  6609. node’s names table. It also allows its clients to obtain the internet addresses of
  6610. entities from their names. This latter operation, known as name lookup (in the names
  6611. directory), requires that NBP install itself as a DDP client and broadcast special
  6612. name-lookup packets to the nodes in a specified zone. These datagrams are sent by NBP
  6613. to the names information socket—socket number 2 in every node using NBP.
  6614.  
  6615. NBP clients can use special meta-characters in place of one or more of the three
  6616. fields of the name of an entity it wishes to look up. The character “=” in the object
  6617. or type field signifies “all possible values”. The zone field can be replaced by “*”,
  6618. which signifies “this zone”—the zone in which the NBP client’s node is located. For
  6619. example, an NBP client performing a lookup with the name
  6620.  
  6621.   =:Mailbox@*
  6622.  
  6623. will obtain in return the entity names and internet addresses of all mailboxes in the
  6624. client’s zone (excluding the client’s own names and addresses). The client can specify
  6625. whether one or all of the matching names should be returned.
  6626.  
  6627. NBP clients specify how thorough a name lookup should be by providing NBP with the
  6628. number of times (retry count) that NBP should broadcast the lookup packets and the
  6629. time interval (retry interval) between these retries.
  6630.  
  6631. As noted above, ALAP and DDP provide “best effort” delivery services with no recovery
  6632. mechanism when packets are lost or discarded because of errors. Although for many
  6633. situations such a service suffices, the AppleTalk Transaction Protocol (ATP) provides
  6634. a reliable loss-free transport service. ATP uses transactions, consisting of a transaction
  6635. request and a transaction response, to deliver data reliably. Each transaction is
  6636. assigned a 16-bit transaction ID number to distinguish it from other transactions. A
  6637. transaction request is retransmitted by ATP until a complete response has been received,
  6638. thus allowing for recovery from packet-loss situations. The retry interval and retry
  6639. count are specified by the ATP client sending the request.
  6640.  
  6641. Although transaction requests must be contained in a single datagram, transaction
  6642. responses can consist of as many as eight datagrams. Each datagram in a response is
  6643. assigned a sequence number from 0 to 7, to indicate its ordering within the response.
  6644.  
  6645. ATP is a DDP client, and uses the services provided by DDP to transmit requests and
  6646. responses. ATP supports both at-least-once and exactly-once transactions. Four of the
  6647. bytes in an ATP header, called the user bytes, are provided for use by ATP’s clients—they’re
  6648. ignored by ATP.
  6649.  
  6650. ATP’s transaction model and means of recovering from datagram loss are covered in
  6651. detail below.
  6652.  
  6653. The Echo Protocol (EP) provides an echoing service through static socket number 4
  6654. known as the echoer socket.  The echoer listens for packets received through this
  6655. socket.  Any correctly formed packet sent to the echoer socket on a node will be
  6656. echoed back to its sender.
  6657.  
  6658. This simple protocol can be used for two important purposes:
  6659.  
  6660.   •  EP can be used by any Datagram Delivery Protocol (DDP) client to
  6661.      determine if a particular node (known to have an echoer) is accessible
  6662.      over an internet.
  6663.   •  EP is useful in determining the average time it takes for a packet to
  6664.      travel to a remote node and back.  This is very helpful in developing
  6665.      client-dependent heuristics for estimating the timeouts to be specified
  6666.      by clients of ATP, ASP, and other protocols.
  6667.  
  6668. Programs cannot access EP directly via the AppleTalk Manager.  The EP implementation
  6669. exists solely to respond to EP requests sent by other nodes.  EP is a DDP client
  6670. residing on statically-assigned socket 4, the echoing socket.  Clients wishing to
  6671. send EP requests (and receive EP responses) should use the Datagram Delivery Protocol
  6672. (DDP) to send the appropriate packet.  For more information about the EP packet
  6673. format, see Inside AppleTalk.
  6674.  
  6675. The AppleTalk Session Protocol (ASP) provides for the setting up, maintaining and
  6676. closing down of a session.  A session is a logical relationship between two network
  6677. entities, a workstation and a server.  The workstation tells the server what to do,
  6678. and the server responds with the appropriate actions.  ASP makes sure that the session
  6679. dialog is maintained in the correct sequence and that both ends of the conversation
  6680. are properly participating.
  6681.  
  6682. ASP will generally be used between two communicating network entities where one is
  6683. providing a service to the other (for example, a server is providing a service to a
  6684. workstation) and the service provided is state-dependent.  That is, the response to a
  6685. particular request from an entity is dependent upon other previous requests from that
  6686. entity.  For example, a request to read bytes from a file is dependent upon a previous
  6687. request to open that file in the first place.  However, a request to return the time
  6688. of day is independent of all such previous requests.
  6689.  
  6690. When the service provided is state-dependent, requests must be delivered to the
  6691. server in the same order as generated by the workstation.  ASP guarantees requests
  6692. are delivered to the server in the order in which they are issued, and that duplicate
  6693. requests are never delivered (another requirement of state-dependent service).
  6694.  
  6695. ASP is an asymmetric protocol, providing one set of services to the workstation and a
  6696. different set of services to the server.
  6697.  
  6698. ASP workstation clients initiate (open) sessions, send requests (commands) on that
  6699. session, and close sessions down.  ASP server clients receive and respond
  6700. (through command replies) to these requests.  ASP guarantees that these requests are
  6701. delivered in the same order as they are made, and without duplication.  ASP is also
  6702. responsible for closing down the session if one end fails or becomes unreachable, and
  6703. will inform its client (either server or workstation) of the action.
  6704.  
  6705. ASP also provides various additional services, such as allowing a workstation to
  6706. obtain server status information without opening a session to a server, writing
  6707. blocks of data from the workstation to the server end of the session, and providing
  6708. the ability for a server to send an attention message to the workstation.
  6709.  
  6710. ASP assumes that the workstation client has a mechanism for looking up the network
  6711. address of the server with which it wants to set up a session.
  6712. (Generally this is done using the AppleTalk Name Binding Protocol.)
  6713.  
  6714. Both ends of the session periodically check to see that the other end of the session
  6715. is still responsive.  If one end fails or becomes unreachable the other end closes
  6716. the session.
  6717.  
  6718. ASP is a client of ATP and calls ATP for transport services.
  6719.  
  6720. ASP does not
  6721.  
  6722.   •  ensure that consecutive commands complete in the order in which they
  6723.      were sent (and delivered) to the server
  6724.   •  understand or interpret the syntax or the semantics of the commands
  6725.      sent to the server by the workstation
  6726.   •  allow the server to send commands to the workstation  (The server
  6727.      is allowed to alert the workstation through the server’s attention
  6728.      mechanism only.)
  6729.  
  6730. Note:  The .XPP driver does implement the workstation side of the
  6731.        AppleTalk Filing Protocol login command.
  6732.  
  6733. The AppleTalk Filing Protocol (AFP) allows a workstation on an AppleTalk network to
  6734. access files on an AFP file server.  AFP specifies a remote filing system that provides
  6735. user authentication and an access control mechanism that supports volume and folder-level
  6736. access rights.  For details of AFP, refer to Inside AppleTalk.
  6737.  
  6738. _______________________________________________________________________________
  6739.  
  6740.  
  6741. æKY AppleTalk…Transaction…Protocol
  6742. æC »APPLETALK TRANSACTION PROTOCOL                           AppleTalkManager
  6743. _______________________________________________________________________________
  6744.  
  6745. This section covers ATP in greater depth, providing more detail about three of its
  6746. fundamental concepts:  transactions, buffer allocation, and recovery of lost datagrams.
  6747.  
  6748. _______________________________________________________________________________
  6749.  
  6750. »Transactions
  6751.  
  6752. A transaction is a interaction between two ATP clients, known as the requester and
  6753. the responder. The requester calls the .ATP driver in its node to send a transaction
  6754. request (TReq) to the responder, and then awaits a response. The TReq is received by
  6755. the .ATP driver in the responder’s node and is delivered to the responder. The responder
  6756. then calls its .ATP driver to send back a transaction response (TResp), which is
  6757. received by the requester’s .ATP driver and delivered to the requester. Figure 3
  6758. illustrates this process.
  6759.  
  6760. •••Refer to Figure 3.•••
  6761.  
  6762. Figure 3–Transaction Process
  6763.  
  6764. Simple examples of transactions are:
  6765.  
  6766.   •  read a counter, reset it and send back the value read
  6767.   •  read six sectors of a disk and send back the data read
  6768.   •  write the data sent in the TReq to a printer
  6769.  
  6770. A basic assumption of the transaction model is that the amount of ATP data sent in
  6771. the TReq specifying the operation to be performed is small enough to fit in a single
  6772. datagram. A TResp, on the other hand, may span several datagrams, as in the second
  6773. example. Thus, a TReq is a single datagram, while a TResp consists of up to eight
  6774. datagrams, each of which is assigned a sequence number from 0 to 7 to indicate its
  6775. position in the response.
  6776.  
  6777. The requester must, before calling for a TReq to be sent, set aside enough buffer
  6778. space to receive the datagram(s) of the TResp. The number of buffers allocated (in
  6779. other words, the maximum number of datagrams that the responder can send) is indicated
  6780. in the TReq by an eight-bit bit map. The bits of this bit map are numbered 0 to 7
  6781. (the least significant bit being number 0); each bit corresponds to the response
  6782. datagram with the respective sequence number.
  6783.  
  6784. _______________________________________________________________________________
  6785.  
  6786. »Datagram Loss Recovery
  6787.  
  6788. The way that ATP recovers from datagram loss situations is best explained by an
  6789. example; see Figure 4. Assume that the requester wants to read six sectors of 512
  6790. bytes each from the responder’s disk. The requester puts aside six 512-byte buffers
  6791. (which may or may not be contiguous) for the response datagrams, and calls ATP to
  6792. send a TReq. In this TReq the bit map is set to binary 00111111 or decimal 63. The
  6793. TReq carries a 16-bit transaction ID, generated by the requester’s .ATP driver before
  6794. sending it. (This example assumes that the requester and responder have already
  6795. agreed that each buffer can hold 512
  6796. bytes.) The TReq is delivered to the responder, which reads the six disk sectors and
  6797. sends them back, through ATP, in TResp datagrams bearing sequence numbers 0 through
  6798. 5. Each TResp datagram also carries exactly the same transaction ID as the TReq to
  6799. which they’re responding.
  6800.  
  6801. There are several ways that datagrams may be lost in this case. The original TReq
  6802. could be lost for one of many reasons. The responding node might be too busy to
  6803. receive the TReq or might be out of buffers for receiving it, there could be an
  6804. undetected collision on the network, a bit error in the transmission line, and so on.
  6805. To recover from such errors, the requester’s .ATP driver maintains an ATP retry timer
  6806. for each transaction sent. If this timer expires and the complete TResp has not been
  6807. received, the TReq is retransmitted and the retry timer is restarted.
  6808.  
  6809. A second error situation occurs when one or more of the TResp datagrams isn’t received
  6810. correctly by the requester’s .ATP driver (datagram 1 in Figure 4). Again, the retry
  6811. timer will expire and the complete TResp will not have been received; this will
  6812. result in a retransmission of the TReq. However, to avoid unnecessary retransmission
  6813. of the TResp datagrams already properly received, the bit map of this retransmitted
  6814. TReq is modified to reflect only those datagrams not yet received. Upon receiving
  6815. this TReq, the responder retransmits only the missing response datagrams.
  6816.  
  6817. Another possible failure is that the responder’s .ATP driver goes down or the responder
  6818. becomes unreachable through the underlying network system. In this case, retransmission
  6819. of the TReq could continue indefinitely. To avoid this situation, the requester
  6820. provides a maximum retry count; if this count is exceeded, the requester’s .ATP
  6821. driver returns an appropriate error message to the requester.
  6822.  
  6823. •••Refer to Figure 4.•••
  6824.  
  6825. Figure 4–Datagram Loss Recovery
  6826.  
  6827. Note:  There may be situations where, due to an anticipated delay, you’ll
  6828.        want a request to be retransmitted more than 255 times; specifying a
  6829.        retry count of 255 indicates “infinite retries” to ATP and will cause
  6830.        a message to be retransmitted until the request has either been
  6831.        serviced, or been cancelled through a specific call.
  6832. _______________________________________________________________________________
  6833.  
  6834. »THE APPLETALK MANAGER                                            
  6835. _______________________________________________________________________________
  6836.  
  6837. Finally, in our example, what if the responder is able to provide only four disk
  6838. sectors (having reached the end of the disk) instead of the six requested? To handle
  6839. this situation, there’s an end-of-message (EOM) flag in each TResp datagram. In this
  6840. case, the TResp datagram numbered 3 would come with this flag set. The reception of
  6841. this datagram informs the requester’s .ATP driver that TResps numbered 4 and 5 will
  6842. not be sent and should not be expected.
  6843.  
  6844. When the transaction completes successfully (all expected TResp datagrams are received
  6845. or TResp datagrams numbered 0 to n are received with datagram n’s EOM flag set), the
  6846. requester is informed and can then use the data received in the TResp.
  6847.  
  6848. ATP provides two classes of service:  at-least-once (ALO) and exactly-once (XO). The
  6849. TReq datagram contains an XO flag that’s set if XO service is required and cleared if
  6850. ALO service is adequate. The main difference between the two is in the sequence of
  6851. events that occurs when the TReq is received by the responder’s .ATP driver.
  6852.  
  6853. In the case of ALO service, each time a TReq is received (with the XO flag cleared),
  6854. it’s delivered to the responder by its .ATP driver; this is true even for retransmitted
  6855. TReqs of the same transaction. Each time the TReq is delivered, the responder performs
  6856. the requested operation and sends the necessary TResp datagrams. Thus, the requested
  6857. operation is performed at least once, and perhaps several times, until the transaction
  6858. is completed at the requester’s end.
  6859.  
  6860. The at-least-once service is satisfactory in a variety of situations—for instance, if
  6861. the requester wishes to read a clock or a counter being maintained at the responder’s
  6862. end. However, in other circumstances, repeated execution of the requested operation
  6863. is unacceptable. This is the case, for instance, if the requester is sending data to
  6864. be printed at the responding end; exactly-once service is designed for such situations.
  6865.  
  6866. The responder’s .ATP driver maintains a transactions list of recently received XO
  6867. TReqs. Whenever a TReq is received with its XO flag set, the driver goes through this
  6868. list to see if this is a retransmitted TReq. If it’s the first TReq of a transaction,
  6869. it’s entered into the list and delivered to the responder. The responder executes the
  6870. requested operation and calls its driver to send a TResp. Before sending it out, the
  6871. .ATP driver saves the TResp in the list.
  6872.  
  6873. When a retransmitted TReq for the same XO transaction is received, the responder’s
  6874. .ATP driver will find a corresponding entry in the list. The retransmitted TReq is
  6875. not delivered to the responder; instead, the driver automatically retransmits the
  6876. response datagrams that were saved in the list. In this way, the responder never sees
  6877. the retransmitted TReqs and the requested operation is performed only once.
  6878.  
  6879. ATP must include a mechanism for eventually removing XO entries from the responding
  6880. end’s transaction list; two provisions are made for this. When the requester’s .ATP
  6881. driver has received all the TResp datagrams of a particular transaction, it sends a
  6882. datagram known as a transaction release (TRel); this tells the responder’s .ATP
  6883. driver to remove the transaction from the list. However, the TRel could be lost in
  6884. the network (or the responding end may die, and so on), leaving the entry in the list
  6885. forever. To account for this situation, the responder’s .ATP driver maintains a
  6886. release timer for each transaction. If this timer expires and no activity has occurred
  6887. for the transaction, its entry is removed from the transactions list.
  6888.  
  6889. _______________________________________________________________________________
  6890.  
  6891.  
  6892. æKY About…the…AppleTalk…Manager
  6893. æC »ABOUT THE APPLETALK MANAGER                              AppleTalkManager
  6894. _______________________________________________________________________________
  6895.  
  6896. The AppleTalk Manager is divided into three parts (see Figure 5):
  6897.  
  6898.   •  A lower-level driver called “.MPP” that contains code to implement ALAP,
  6899.      DDP, NBP, and the RTMP stub; this includes separate code resources loaded
  6900.      in when an NBP name is registered or looked up.
  6901.   •  A higher-level driver called “.ATP” that implements ATP.
  6902.   •  A Pascal interface to these two drivers, which is a set of Pascal data
  6903.      types and routines to aid Pascal programmers in calling the AppleTalk
  6904.      Manager.
  6905.  
  6906. •••Refer to Figure 5.•••
  6907.  
  6908. Figure 5–Calling the AppleTalk Manager
  6909.  
  6910. The two drivers and the interface to them are not in ROM; your application must link
  6911. to the appropriate object files.
  6912.  
  6913. Pascal programmers make calls to the AppleTalk Manager’s Pascal interface, which in
  6914. turn makes Device Manager Control calls to the two drivers. Assembly-language programmers
  6915. make Device Manager Control calls directly to the drivers.
  6916.  
  6917. Note:  Pascal programmers can, of course, make PBControl calls directly
  6918.        if they wish.
  6919.  
  6920. The AppleTalk Manager provides ALAP routines that allow a program to:
  6921.  
  6922.   •  send a frame to another node
  6923.   •  receive a frame from another node
  6924.   •  add a protocol handler to the protocol handler table
  6925.   •  remove a protocol handler from the protocol handler table
  6926.  
  6927. Each node may have up to four protocol handlers in its protocol handler table, two of
  6928. which are currently used by DDP.
  6929.  
  6930. By calling DDP, socket clients can:
  6931.  
  6932.   •  send a datagram via a socket
  6933.   •  receive a datagram via a socket
  6934.   •  open a socket and add a socket listener to the socket table
  6935.   •  close a socket and remove a socket listener from the socket table
  6936.  
  6937. Each node may have up to 12 open sockets in its socket table.
  6938.  
  6939. Programs cannot access RTMP directly via the AppleTalk Manager; RTMP exists solely
  6940. for the purpose of providing DDP with routing information.
  6941.  
  6942. The NBP code allows a socket client to:
  6943.  
  6944.   •  register the name and socket number of an entity in the node’s names table
  6945.   •  determine the address (and confirm the existence) of an entity
  6946.   •  delete the name of an entity from the node’s names table
  6947.  
  6948. The AppleTalk Manager’s .ATP driver allows a socket client to do the following:
  6949.  
  6950.   •  open a responding socket to receive requests
  6951.   •  send a request to another socket and get back a response
  6952.   •  receive a request via a responding socket
  6953.   •  send a response via a responding socket
  6954.   •  close a responding socket
  6955.  
  6956. Note:  Although the AppleTalk Manager provides four different protocols
  6957.        for your use, you’re not bound to use all of them. In fact, most
  6958.        programmers will use only the NBP and ATP protocols.
  6959.  
  6960. AppleTalk communicates via channel B of the Serial Communications Controller
  6961. (SCC). When the Macintosh is started up with a disk containing the AppleTalk code,
  6962. the status of serial port B is checked. If port B isn’t being used by another device
  6963. driver, and is available for use by AppleTalk, the .MPP driver is loaded into the
  6964. system heap. On a Macintosh 128K, only the MPP code is loaded at system startup; the
  6965. .ATP driver and NBP code are read into the application heap when the appropriate
  6966. commands are issued. On a Macintosh 512K or XL, all AppleTalk code is loaded into the
  6967. system heap at system startup.
  6968.  
  6969. After loading the AppleTalk code, the .MPP driver installs its own interrupt handlers,
  6970. installs a task into the vertical retrace queue, and prepares the SCC for use. It
  6971. then chooses a node ID for the Macintosh and confirms that the node ID isn’t already
  6972. being used by another node on the network.
  6973.  
  6974. Warning:  For this reason it’s imperative that the Macintosh be connected
  6975.           to the AppleTalk network through serial port B (the printer port)
  6976.           before being switched on.
  6977.  
  6978. The AppleTalk Manager also provides Pascal routines for opening and closing the .MPP
  6979. and .ATP drivers. The open calls allow a program to load AppleTalk code at times
  6980. other than system startup. The close calls allow a program to remove the AppleTalk
  6981. code from the Macintosh; the use of close calls is highly discouraged, since other
  6982. co-resident programs are then “disconnected” from AppleTalk. Both sets of calls are
  6983. described in detail under “Calling the AppleTalk Manager from Pascal”.
  6984.  
  6985. Warning:  If, at system startup, serial port B isn’t available for use by
  6986.           AppleTalk, the .MPP driver won’t open. However, a driver doesn’t
  6987.           return an error message when it fails to open. Pascal programmers
  6988.           must ensure the proper opening of AppleTalk by calling one of the
  6989.           two routines for opening the AppleTalk drivers (either MPPOpen or
  6990.           ATPLoad). If AppleTalk was successfully loaded at system startup,
  6991.           these calls will have no effect; otherwise they’ll check the
  6992.           availability of port B, attempt to load the AppleTalk code, and
  6993.           return an appropriate result code.
  6994.  
  6995. Assembly-language note:  Assembly-language programmers can use the Pascal
  6996.                          routines for opening AppleTalk. They can also check
  6997.                          the availability of port B themselves and then decide
  6998.                          whether to open MPP or ATP. Detailed information on
  6999.                          how to do this is provided in the section “Calling
  7000.                          the AppleTalk Manager from Assembly Language”.
  7001.  
  7002. The two AppleTalk device drivers, named .MPP and .ATP, are included in the 128K ROM.
  7003. The AppleTalk Manager, however (the interface to the drivers), is not in ROM; your
  7004. application must link to the appropriate object files.
  7005.  
  7006. On the Macintosh Plus, you need only open the .MPP driver; this will also load the
  7007. .ATP driver and NBP code automatically. Since, in the 128K ROM, device drivers return
  7008. errors, it’s no longer necessary to check whether port B is free and configured for
  7009. AppleTalk. If port B isn’t available, the .MPP driver won’t open and the result code
  7010. portInUse or portNotCf will be returned.
  7011.  
  7012. Assembly-language note:  When called from assembly language, the Datagram
  7013.                          Delivery Protocol (DDP) allows 14 (instead of 12)
  7014.                          open sockets.
  7015.  
  7016. The changes to the AppleTalk manager increase functionality and resources. Two interfaces
  7017. for the AppleTalk Manager calls are discussed: the new or preferred interface and the
  7018. alternate interface. Picking a node address in the server range, sending packets to
  7019. one’s own node, multiple concurrent NBP requests, sending ATP requests through a
  7020. specified socket and two new ATP calls are also discussed in this section. These
  7021. calls can only be made with the preferred interface.
  7022.  
  7023. _______________________________________________________________________________
  7024.  
  7025.  
  7026. æKY Calling…the…AppleTalk…Manager…from…Pascal
  7027. æC »CALLING THE APPLETALK MANAGER FROM PASCAL                AppleTalkManager
  7028. _______________________________________________________________________________
  7029.  
  7030. This section discusses how to use the AppleTalk Manager from Pascal. Equivalent
  7031. assembly-language information is given in the “Calling the AppleTalk Manager from
  7032. Assembly Language” section.
  7033.  
  7034. You can execute many AppleTalk Manager routines either synchronously (meaning that
  7035. the application can’t continue until the routine is completed) or asynchronously
  7036. (meaning that the application is free to perform other tasks while the routine is
  7037. being executed).
  7038.  
  7039. When an application calls an AppleTalk Manager routine asynchronously, an I/O request
  7040. is placed in the appropriate driver’s I/O queue, and control returns to the calling
  7041. program—possibly even before the actual I/O is completed. Requests are taken from the
  7042. queue one at a time, and processed; meanwhile, the calling program is free to work on
  7043. other things.
  7044.  
  7045. The routines that can be executed asynchronously contain a Boolean parameter called
  7046. async. If async is TRUE, the call is executed asynchronously; otherwise the call is
  7047. executed synchronously. Every time an asynchronous routine call is completed, the
  7048. AppleTalk Manager posts a network event. The message field of the event record will
  7049. contain a handle to the parameter block that was used to make that call.
  7050.  
  7051. Most AppleTalk Manager routines return an integer result code of type OSErr. Each
  7052. routine description lists all of the applicable result codes generated by the AppleTalk
  7053. Manager, along with a short description of what the result code means. Lengthier
  7054. explanations of all the result codes can be found in the summary at the end of the
  7055. chapter. Result codes from other parts of the Operating System may also be returned.
  7056. (See Appendix A for a list of all result codes.)
  7057.  
  7058. Many Pascal calls to the AppleTalk Manager require information passed in a parameter
  7059. block of type ABusRecord. The exact content of an ABusRecord depends on the protocol
  7060. being called:
  7061.  
  7062. TYPE  ABProtoType  =  (lapProto,ddpProto,nbpProto,atpProto);
  7063.       ABusRecord   =  RECORD
  7064.                         abOpcode:        ABCallType; {type of call}
  7065.                         abResult:        INTEGER;    {result code}
  7066.                         abUserReference: LONGINT;    {for your use}
  7067.                         CASE ABProtoType OF
  7068.                           lapProto:
  7069.                             . . .     {ALAP parameters}
  7070.                           ddpProto:
  7071.                             . . .     {DDP parameters}
  7072.                           nbpProto:
  7073.                             . . .     {NBP parameters}
  7074.                           atpProto:
  7075.                             . . .     {ATP parameters}
  7076.                         END;
  7077.                       END;
  7078.  
  7079.       ABRecPtr     = ^ABusRecord;
  7080.       ABRecHandle  = ^ABRecPtr;
  7081.  
  7082. The value of the abOpcode field is inserted by the AppleTalk Manager when the call is
  7083. made, and is always a member of the following set:
  7084.  
  7085. TYPE  ABCallType = (tLAPRead,tLAPWrite,tDDPRead,tDDPWrite,tNBPLookup,
  7086.                     tNBPConfirm,tNBPRegister,tATPSndRequest,
  7087.                     tATPGetRequest,tATPSdRsp,tATPAddRsp,tATPRequest,
  7088.                     tATPRespond);
  7089.  
  7090. The abUserReference field is available for use by the calling program in any way it
  7091. wants. This field isn’t used by the AppleTalk Manager routines or drivers.
  7092.  
  7093. The size of an ABusRecord data structure in bytes is given by one of the following
  7094. constants:
  7095.  
  7096. CONST  lapSize = 20;
  7097.        ddpSize = 26;
  7098.        nbpSize = 26;
  7099.        atpSize = 56;
  7100.  
  7101. Variables of type ABusRecord must be allocated in the heap with Memory Manager NewHandle
  7102. calls. For example:
  7103.  
  7104.   myABRecord := ABRecHandle(NewHandle(ddpSize))
  7105.  
  7106. Warning:  These Memory Manager calls can’t be made inside interrupts.
  7107.  
  7108. Routines that are executed asynchronously return control to the calling program with
  7109. the result code noErr as soon as the call is placed in the driver’s I/O queue. This
  7110. isn’t an indication of successful call completion; it simply indicates that the call
  7111. was successfully queued to the appropriate driver. To determine when the call is
  7112. actually completed, you can either check for a network event or poll the abResult
  7113. field of the call’s ABusRecord. The abResult field, set to 1 when the call is made,
  7114. receives the actual result code upon completion of the call.
  7115.  
  7116. Warning:  A data structure of type ABusRecord is often used by the AppleTalk
  7117.           Manager during an asynchronous call, and so is locked by the
  7118.           AppleTalk Manager. Don’t attempt to unlock or use such a variable.
  7119.  
  7120. Each routine description includes a list of the ABusRecord fields affected by the
  7121. routine. The arrow next to each field name indicates whether it’s an input, output,
  7122. or input/output parameter:
  7123.  
  7124. Arrow    Meaning
  7125.   -->    Parameter is passed to the routine
  7126.   <--    Parameter is returned by the routine
  7127.   <->    Parameter is passed to and returned by the routine
  7128.  
  7129. _______________________________________________________________________________
  7130.  
  7131. »Opening and Closing AppleTalk
  7132.  
  7133. •••Refer to Technical Note #224:•••
  7134.  
  7135. FUNCTION MPPOpen :  OSErr; [Not in ROM]
  7136.  
  7137. MPPOpen first checks whether the .MPP driver has already been loaded; if it has,
  7138. MPPOpen does nothing and returns noErr. If MPP hasn’t been loaded, MPPOpen attempts
  7139. to load it into the system heap. If it succeeds, it then initializes the driver’s
  7140. variables and goes through the process of dynamically assigning a node ID to that
  7141. Macintosh. On a Macintosh 512K or XL, it also loads the .ATP driver and NBP code into
  7142. the system heap.
  7143.  
  7144. If serial port B isn’t configured for AppleTalk, or is already in use, the .MPP
  7145. driver isn’t loaded and an appropriate result code is returned.
  7146.  
  7147. Result codes    noErr        No error
  7148.                 portInUse    Port B is already in use
  7149.                 portNotCf    Port B not configured for AppleTalk
  7150.  
  7151. FUNCTION MPPClose :  OSErr; [Not in ROM]
  7152.  
  7153. MPPClose removes the .MPP driver, and any data structures associated with it, from
  7154. memory. If the .ATP driver or NBP code were also installed, they’re removed as well.
  7155. MPPClose also returns the use of port B to the Serial Driver.
  7156.  
  7157. Warning:  Since other co-resident programs may be using AppleTalk, it’s
  7158.           strongly recommended that you never use this call. MPPClose will
  7159.           completely disable AppleTalk; the only way to restore AppleTalk
  7160.           is to call MPPOpen again.
  7161.  
  7162. _______________________________________________________________________________
  7163.  
  7164. »AppleTalk Link Access Protocol
  7165.  
  7166. »Data Structures
  7167.  
  7168. ALAP calls use the following ABusRecord fields:
  7169.  
  7170. lapProto:
  7171.     (lapAddress:    LAPAdrBlock; {destination or source node ID}
  7172.      lapReqCount:   INTEGER;     {length of frame data or buffer size in bytes}
  7173.      lapActCount:   INTEGER;     {number of frame data bytes actually received}
  7174.      lapDataPtr:    Ptr);        {pointer to frame data or pointer to buffer}
  7175.  
  7176. When an ALAP frame is sent, the lapAddress field indicates the ID of the destination
  7177. node. When an ALAP frame is received, lapAddress returns the ID of the source node.
  7178. The lapAddress field also indicates the ALAP protocol type of the frame:
  7179.  
  7180. TYPE  LAPAdrBlock = PACKED RECORD
  7181.                       dstNodeID:    Byte;  {destination node ID}
  7182.                       srcNodeID:    Byte;  {source node ID}
  7183.                       lapProtType:  ABByte {ALAP protocol type}
  7184.                     END;
  7185.  
  7186. When an ALAP frame is sent, lapReqCount indicates the size of the frame data in bytes
  7187. and lapDataPtr points to a buffer containing the frame data to be sent. When an ALAP
  7188. frame is received, lapDataPtr points to a buffer in which the incoming data can be
  7189. stored and lapReqCount indicates the size of the buffer in bytes. The number of bytes
  7190. actually sent or received is returned in the lapActCount field.
  7191.  
  7192. Each ALAP frame contains an eight-bit ALAP protocol type in the header. ALAP protocol
  7193. types 128 through 255 are reserved for internal use by ALAP, hence the declaration:
  7194.  
  7195. TYPE  ABByte = 1..127; {ALAP protocol type}
  7196.  
  7197. Warning:  Don’t use ALAP protocol type values 1 and 2; they’re reserved
  7198.           for use by DDP. Value 3 through 15 are reserved for internal
  7199.           use by Apple and also shouldn’t be used.
  7200.  
  7201. »Using ALAP
  7202.  
  7203. Most programs will never need to call ALAP, because higher-level protocols will
  7204. automatically call it as necessary. If you do want to send a frame directly via ALAP,
  7205. call the LAPWrite function. If you want to read ALAP frames, you have two choices:
  7206.  
  7207.   •  Call LAPOpenProtocol with NIL for protoPtr (see below); this installs
  7208.      the default protocol handler provided by the AppleTalk Manager. Then
  7209.      call LAPRead to receive frames.
  7210.   •  Write your own protocol handler, and call LAPOpenProtocol to add it
  7211.      to the node’s protocol handler table. The ALAP code will examine every
  7212.      incoming frame and send all those with the correct ALAP protocol type
  7213.      to your protocol handler. See the section “Protocol Handlers and Socket
  7214.      Listeners” for information on how to write a protocol handler.
  7215.  
  7216. When your program no longer wants to receive frames with a particular ALAP protocol
  7217. type value, it can call LAPCloseProtocol to remove the corresponding protocol handler
  7218. from the protocol handler table.
  7219.  
  7220. »ALAP Routines
  7221.  
  7222. FUNCTION LAPOpenProtocol (theLAPType:  ABByte;
  7223.                           protoPtr:  Ptr) :  OSErr; [Not in ROM]
  7224.  
  7225. LAPOpenProtocol adds the ALAP protocol type specified by theLAPType to the
  7226. node’s protocol table. If you provide a pointer to a protocol handler in protoPtr,
  7227. ALAP will send each frame with an ALAP protocol type of theLAPType to that protocol
  7228. handler.
  7229.  
  7230. If protoPtr is NIL, the default protocol handler will be used for receiving frames
  7231. with an ALAP protocol type of theLAPType. In this case, to receive a frame you must
  7232. call LAPRead to provide the default protocol handler with a buffer for placing the
  7233. data. If, however, you’ve written your own protocol handler and protoPtr points to
  7234. it, your protocol handler will have the responsibility for receiving the frame and
  7235. it’s not necessary to call LAPRead.
  7236.  
  7237. Result codes    noErr         No error
  7238.                 lapProtErr    Error attaching protocol type
  7239.  
  7240. FUNCTION LAPCloseProtocol (theLAPType:  ABByte) :  OSErr; [Not in ROM]
  7241.  
  7242. LAPCloseProtocol removes from the node’s protocol table the specified ALAP protocol
  7243. type, as well as its protocol handler.
  7244.  
  7245. Warning:  Don’t close ALAP protocol type values 1 or 2. If you close these
  7246.           protocol types, DDP will be disabled; once disabled, the only way
  7247.           to restore DDP is to restart the system, or to close and then
  7248.           reopen AppleTalk.
  7249.  
  7250. Result codes    noErr         No error
  7251.                 lapProtErr    Error detaching protocol type
  7252.  
  7253. FUNCTION LAPWrite (abRecord:  ABRecHandle;
  7254.                    async:  BOOLEAN) :  OSErr; [Not in ROM]
  7255.  
  7256. ABusRecord
  7257.   <--    abOpcode                {always tLAPWrite}
  7258.   <--    abResult                {result code}
  7259.   -->    abUserReference         {for your use}
  7260.   -->    lapAddress.dstNodeID    {destination node ID}
  7261.   -->    lapAddress.lapProtType  {ALAP protocol type}
  7262.   -->    lapReqCount             {length of frame data}
  7263.   -->    lapDataPtr              {pointer to frame data}
  7264.  
  7265. LAPWrite sends a frame to another node. LAPReqCount and lapDataPtr specify the length
  7266. and location of the data to send. The lapAddress.lapProtType field indicates the ALAP
  7267. protocol type of the frame and the lapAddress.dstNodeID indicates the node ID of the
  7268. node to which the frame should be sent.
  7269.  
  7270. Note:  The first two bytes of an ALAP frame’s data must contain the length
  7271.        in bytes of that data, including the length bytes themselves.
  7272.  
  7273. Result codes    noErr            No error
  7274.                 excessCollsns    Unable to contact destination node;
  7275.                                  packet not sent
  7276.                 ddpLenErr        ALAP data length too big
  7277.                 lapProtErr       Invalid ALAP protocol type
  7278.  
  7279. FUNCTION LAPRead (abRecord:  ABRecHandle;
  7280.                   async:  BOOLEAN) :  OSErr; [Not in ROM]
  7281.  
  7282. ABusRecord
  7283.   <--    abOpcode                {always tLAPRead}
  7284.   <--    abResult                {result code}
  7285.   -->    abUserReference         {for your use}
  7286.   <--    lapAddress.dstNodeID    {destination node ID}
  7287.   <--    lapAddress.srcNodeID    {source node ID}
  7288.   -->    lapAddress.lapProtType  {ALAP protocol type}
  7289.   -->    lapReqCount             {buffer size in bytes}
  7290.   <--    lapActCount             {number of frame data bytes actually received}
  7291.   -->    lapDataPtr              {pointer to buffer}
  7292.  
  7293. LAPRead receives a frame from another node. LAPReqCount and lapDataPtr specify the
  7294. size and location of the buffer that will receive the frame data. If the buffer isn’t
  7295. large enough to hold all of the incoming frame data, the extra bytes will be discarded
  7296. and buf2SmallErr will be returned. The number of bytes actually received is returned
  7297. in lapActCount. Only frames with ALAP protocol type equal to lapAddress.lapProtType
  7298. will be received. The node IDs of the frame’s source and destination nodes are returned
  7299. in lapAddress.srcNodeID and lapAddress.dstNodeID. You can determine whether the
  7300. packet was broadcast to you by examining the value of lapAddress.dstNodeID—if the
  7301. packet was broadcast it’s equal to 255, otherwise it’s equal to your node ID.
  7302.  
  7303. Note:  You should issue LAPRead calls only for ALAP protocol types that were
  7304.        opened (via LAPOpenProtocol) to use the default protocol handler.
  7305.  
  7306. Warning:  If you close a protocol type for which there are still LAPRead
  7307.           calls pending, the calls will be canceled but the memory occupied
  7308.           by their ABusRecords will not be released. For this reason, before
  7309.           closing a protocol type, call LAPRdCancel to cancel any pending
  7310.           LAPRead calls associated with that protocol type.
  7311.  
  7312. Result codes    noErr           No error
  7313.                 buf2SmallErr    Frame too large for buffer
  7314.                 readQErr        Invalid protocol type or protocol type not
  7315.                                 found in table
  7316.  
  7317. FUNCTION LAPRdCancel (abRecord:  ABRecHandle) :  OSErr; [Not in ROM]
  7318.  
  7319. Given the handle to the ABusRecord of a previously made LAPRead call, LAPRdCancel
  7320. dequeues the LAPRead call, provided that a packet satisfying the LAPRead has not
  7321. already arrived. LAPRdCancel returns noErr if the LAPRead call is successfully removed
  7322. from the queue. If LAPRdCancel returns recNotFnd, check the abResult field to verify
  7323. that the LAPRead has been completed and determine its outcome.
  7324.  
  7325. Result codes    noErr        No error
  7326.                 readQErr     Invalid protocol type or protocol type not
  7327.                              found in table
  7328.                 recNotFnd    ABRecord not found in queue
  7329.  
  7330. »Example
  7331.  
  7332. This example sends an ALAP packet synchronously and waits asynchronously for a response.
  7333. Assume that both nodes are using a known protocol type (in this case, 73) to receive
  7334. packets, and that the destination node has a node ID of 4.
  7335.  
  7336. VAR
  7337.   myABRecord: ABRecHandle;
  7338.   myBuffer: PACKED ARRAY [0..599] OF CHAR; {buffer for both send and receive}
  7339.   myLAPType: Byte;
  7340.   errCode, index, dataLen: INTEGER;
  7341.   someText: Str255;
  7342.   async: BOOLEAN;
  7343.  
  7344. BEGIN
  7345.   errCode := MPPOpen;
  7346.   IF errCode <> noErr THEN
  7347.     WRITELN('Error in opening AppleTalk')
  7348.     {Maybe serial port B isn't available for use by AppleTalk}
  7349.   ELSE
  7350.     BEGIN
  7351.     {Call Memory Manager to allocate ABusRecord}
  7352.     myABRecord := ABRecHandle(NewHandle(lapSize));
  7353.     myLAPType := 73;
  7354.    {Enter myLAPType into protocol handler table and install default handler to }
  7355.     { service frames of that ALAP type. No packets of that ALAP type will be }
  7356.     { received until we call LAPRead.}
  7357.     errCode := LAPOpenProtocol(myLAPType, NIL);
  7358.     IF errCode <> noErr THEN
  7359.       WRITELN('Error while opening the protocol type')
  7360.       {Have we opened too many protocol types? Remember that DDP uses two of }
  7361.       { them.}
  7362.     ELSE
  7363.       BEGIN
  7364.       {Prepare data to be sent}
  7365.       someText := 'This data will be in the ALAP data area';
  7366.       {The .MPP implementation requires that the first two bytes of the ALAP }
  7367.       { data field contain the length of the data, including the length bytes }
  7368.       { themselves.}
  7369.       dataLen := LENGTH(someText) + 2;
  7370.       buffer[0] := CHR(dataLen DIV 256); {high byte of data length}
  7371.       buffer[1] := CHR(dataLen MOD 256); {low byte of data length}
  7372.       FOR index := 1 TO dataLen - 2 DO {stuff buffer with packet data}
  7373.         buffer[index + 1] := someText[index];
  7374.       async := FALSE;
  7375.       WITH myABRecord^^ DO {fill parameters in the ABusRecord}
  7376.         BEGIN
  7377.         lapAddress.lapProtType := myLAPType;
  7378.         lapAddress.dstNodeID := 4;
  7379.         lapReqCount := dataLen;
  7380.         lapDataPtr := @buffer;
  7381.         END;
  7382.       {Send the frame}
  7383.       errCode := LAPWrite(myABRecord, async);
  7384.       {In the case of a sync call, errCode and the abResult field of }
  7385.       { the myABRecord will contain the same result code. We can also }
  7386.       { reuse myABRecord, since we know whether the call has completed.}
  7387.       IF errCode <> noErr THEN
  7388.         WRITELN('Error while writing out the packet')
  7389.         {Maybe the receiving node wasn't on-line}
  7390.       ELSE
  7391.         BEGIN
  7392.         {We have sent out the packet and are now waiting for a response. We }
  7393.         { issue an async LAPRead call so that we don't “hang” waiting for a }
  7394.         { response that may not come.}
  7395.         async := TRUE;
  7396.         WITH myABRecord^^ DO
  7397.           BEGIN
  7398.           lapAddress.lapProtType := myLAPType;
  7399.           {ALAP type we want to receive }
  7400.           lapReqCount := 600; {our buffer is maximum size}
  7401.           lapDataPtr := @buffer;
  7402.           END;
  7403.         errCode := LAPRead(myABRecord, async); {wait for a packet}
  7404.         IF errCode <> noErr THEN
  7405.           WRITELN('Error while trying to queue up a LAPRead')
  7406.           {Was the protocol handler installed correctly?}
  7407.         ELSE
  7408.           BEGIN
  7409.           {We can either sit here in a loop and poll the abResult }
  7410.           { field or just exit our code and use the event }
  7411.           { mechanism to flag us when the packet arrives.}
  7412.           CheckForMyEvent; {your procedure for checking for a network event}
  7413.           errCode := LAPCloseProtocol(myLAPType);
  7414.           IF errCode <> noErr THEN
  7415.             WRITELN('Error while closing the protocol type');
  7416.           END;
  7417.         END;
  7418.       END;
  7419.     END;
  7420. END.
  7421.  
  7422.  
  7423. _______________________________________________________________________________
  7424.  
  7425. »Datagram Delivery Protocol
  7426.  
  7427. »Data Structures
  7428.  
  7429. DDP calls use the following ABusRecord fields:
  7430.  
  7431. ddpProto:
  7432.     (ddpType:      Byte;       {DDP protocol type}
  7433.      ddpSocket:    Byte;       {source or listening socket number}
  7434.      ddpAddress:   AddrBlock;  {destination or source socket address}
  7435.      ddpReqCount:  INTEGER;    {length of datagram data or buffer size in bytes}
  7436.      ddpActCount:  INTEGER;    {number of bytes actually received}
  7437.      ddpDataPtr:   Ptr;        {pointer to buffer}
  7438.      ddpNodeID:    Byte);      {original destination node ID}
  7439.  
  7440. When a DDP datagram is sent, ddpReqCount indicates the size of the datagram data in
  7441. bytes and ddpDataPtr points to a buffer containing the datagram data. DDPSocket
  7442. specifies the socket from which the datagram should be sent. DDPAddress is the internet
  7443. address of the socket to which the datagram should be sent:
  7444.  
  7445. TYPE  AddrBlock = PACKED RECORD
  7446.                     aNet:     INTEGER;  {network number}
  7447.                     aNode:    Byte;     {node ID}
  7448.                     aSocket:  Byte      {socket number}
  7449.                   END;
  7450.  
  7451. Note:  The network number you specify in ddpAddress.aNet tells MPP whether
  7452.        to create a long header (for an internet) or a short header (for a
  7453.        local network only). A short DDP header will be sent if ddpAddress.aNet
  7454.        is 0 or equal to the network number of the local network.
  7455.  
  7456. When a DDP datagram is received, ddpDataPtr points to a buffer in which the incoming
  7457. data can be stored and ddpReqCount indicates the size of the buffer in bytes. The
  7458. number of bytes actually sent or received is returned in the ddpActCount field.
  7459. DDPAddress is the internet address of the socket from which the datagram was sent.
  7460.  
  7461. DDPType is the DDP protocol type of the datagram, and ddpSocket specifies the socket
  7462. that will receive the datagram.
  7463.  
  7464. Warning:  DDP protocol types 1 through 15 and DDP socket numbers 1 through 63
  7465.           are reserved by Apple for internal use. Socket numbers 64 through 127
  7466.           are available for experimental use. Use of these experimental sockets
  7467.           isn’t recommended for commercial products, since there’s no mechanism
  7468.           for eliminating conflicting usage by different developers.
  7469.  
  7470. »Using DDP
  7471.  
  7472. Before it can use a socket, the program must call DDPOpenSocket, which adds a socket
  7473. and its socket listener to the socket table. When a program is finished using a
  7474. socket, call DDPCloseSocket, which removes the socket’s entry from the socket table.
  7475. To send a datagram via DDP, call DDPWrite. To receive datagrams, you have two choices:
  7476.  
  7477.   •  Call DDPOpenSocket with NIL for sktListener (see below); this installs
  7478.      the default socket listener provided by the AppleTalk Manager. Then call
  7479.      DDPRead to receive datagrams.
  7480.   •  Write your own socket listener and call DDPOpenSocket to install it. DDP
  7481.      will call your socket listener for every incoming datagram for that
  7482.      socket; in this case, you shouldn’t call DDPRead. For information on how
  7483.      to write a socket listener, see the section “Protocol Handlers and Socket
  7484.      Listeners”.
  7485.  
  7486. To cancel a previously issued DDPRead call (provided it’s still in the queue), call
  7487. DDPRdCancel.
  7488.  
  7489. »DDP Routines
  7490.  
  7491. FUNCTION DDPOpenSocket (VAR theSocket:  Byte;
  7492.                         sktListener:  Ptr) :  OSErr; [Not in ROM]
  7493.  
  7494. DDPOpenSocket adds a socket and its socket listener to the socket table. If theSocket
  7495. is nonzero, it must be in the range 64 to 127, and it specifies the socket’s number;
  7496. if theSocket is 0, DDPOpenSocket dynamically assigns a socket number in the range 128
  7497. to 254, and returns it in theSocket. SktListener contains a pointer to the socket
  7498. listener; if it’s NIL, the default listener will be used.
  7499.  
  7500. If you’re using the default socket listener, you must then call DDPRead to receive a
  7501. datagram (in order to specify buffer space for the default socket listener). If,
  7502. however, you’ve written your own socket listener and sktListener points to it, your
  7503. listener will provide buffers for receiving datagrams and you shouldn’t use DDPRead
  7504. calls.
  7505.  
  7506. DDPOpenSocket will return ddpSktErr if you pass the number of an already opened
  7507. socket, if you pass a socket number greater than 127, or if the socket table is
  7508. full.
  7509.  
  7510. Note:  The range of static socket numbers 1 through 63 is reserved by Apple
  7511.        for internal use. Socket numbers 64 through 127 are available for
  7512.        unrestricted experimental use.
  7513.  
  7514. Result codes    noErr        No error
  7515.                 ddpSktErr    Socket error
  7516.  
  7517. FUNCTION DDPCloseSocket (theSocket:  Byte) :  OSErr; [Not in ROM]
  7518.  
  7519. DDPCloseSocket removes the entry of the specified socket from the socket table and
  7520. cancels all pending DDPRead calls that have been made for that socket. If you pass a
  7521. socket number of 0, or if you attempt to close a socket that isn’t open, DDPCloseSocket
  7522. will return ddpSktErr.
  7523.  
  7524. Result codes    noErr        No error
  7525.                 ddpSktErr    Socket error
  7526.  
  7527. FUNCTION DDPWrite (abRecord:  ABRecHandle; doChecksum:  BOOLEAN;
  7528.                    async:  BOOLEAN) :  OSErr; [Not in ROM]
  7529.  
  7530. ABusRecord
  7531.   <--    abOpcode         {always tDDPWrite}
  7532.   <--    abResult         {result code}
  7533.   -->    abUserReference  {for your use}
  7534.   -->    ddpType          {DDP protocol type}
  7535.   -->    ddpSocket        {source socket number}
  7536.   -->    ddpAddress       {destination socket address}
  7537.   -->    ddpReqCount      {length of datagram data}
  7538.   -->    ddpDataPtr       {pointer to buffer}
  7539.  
  7540. DDPWrite sends a datagram to another socket. DDPReqCount and ddpDataPtr specify the
  7541. length and location of the data to send. The ddpType field indicates the DDP protocol
  7542. type of the frame, and ddpAddress is the complete internet address of the socket to
  7543. which the datagram should be sent. DDPSocket specifies the socket from which the
  7544. datagram should be sent. Datagrams sent over the internet to a node on an AppleTalk
  7545. network different from the sending node’s network have an optional software checksum
  7546. to detect errors that might occur inside the intermediate bridges. If doChecksum is
  7547. TRUE, DDPWrite will compute this checksum; if it’s FALSE, this software checksum
  7548. feature is ignored.
  7549.  
  7550. Note:  The destination socket can’t be in the same node as the program
  7551.        making the DDPWrite call.
  7552.  
  7553. Result codes    noErr          No error
  7554.                 ddpLenErr      Datagram length too big
  7555.                 ddpSktErr      Source socket not open
  7556.                 noBridgeErr    No bridge found
  7557.  
  7558. FUNCTION DDPRead (abRecord:  ABRecHandle; retCksumErrs:  BOOLEAN;
  7559.                   async:  BOOLEAN) :  OSErr; [Not in ROM]
  7560.  
  7561. ABusRecord
  7562.   <--    abOpcode         {always tDDPRead}
  7563.   <--    abResult         {result code}
  7564.   -->    abUserReference  {for your use}
  7565.   <--    ddpType          {DDP protocol type}
  7566.   -->    ddpSocket        {listening socket number}
  7567.   <--    ddpAddress       {source socket address}
  7568.   -->    ddpReqCount      {buffer size in bytes}
  7569.   <--    ddpActCount      {number of bytes actually received}
  7570.   -->    ddpDataPtr       {pointer to buffer}
  7571.   <--    ddpNodeID        {original destination node ID}
  7572.  
  7573. DDPRead receives a datagram from another socket. The size and location of the buffer
  7574. that will receive the data are specified by ddpReqCount and ddpDataPtr. If the buffer
  7575. isn’t large enough to hold all of the incoming frame data, the extra bytes will be
  7576. discarded and buf2SmallErr will be returned. The number of bytes actually received is
  7577. returned in ddpActCount. DDPSocket specifies the socket to receive the datagram (the
  7578. “listening” socket). The node to which the packet was sent is returned in ddpNodeID;
  7579. if the packet was broadcast ddpNodeID will contain 255. The address of the socket
  7580. that sent the packet is returned in ddpAddress. If retCksumErrs is FALSE, DDPRead
  7581. will discard any packets received with an invalid checksum and inform the caller of
  7582. the error. If retCksumErrs is TRUE, DDPRead will deliver all packets, whether or not
  7583. the checksum is valid; it will also notify the caller when there’s a checksum error.
  7584.  
  7585. Note:  The sender of the datagram must be in a different node from the
  7586.        receiver. You should issue DDPRead calls only for receiving datagrams
  7587.        for sockets opened with the default socket listener; see the
  7588.        description of DDPOpenSocket.
  7589.  
  7590. Note:  If the buffer provided isn’t large enough to hold all of the incoming
  7591.        frame data (buf2SmallErr), the checksum can’t be calculated; in this
  7592.        case, DDPRead will deliver packets even if retCksumErrs is FALSE.
  7593.  
  7594. Result codes    noErr           No error
  7595.                 buf2SmallErr    Datagram too large for buffer
  7596.                 cksumErr        Checksum error
  7597.                 ddpLenErr       Datagram length too big
  7598.                 ddpSktErr       Socket error
  7599.                 readQErr        Invalid socket or socket not found in table
  7600.  
  7601. FUNCTION DDPRdCancel (abRecord:  ABRecHandle) :  OSErr; [Not in ROM]
  7602.  
  7603. Given the handle to the ABusRecord of a previously made DDPRead call, DDPRdCancel
  7604. dequeues the DDPRead call, provided that a packet satisfying the DDPRead hasn’t
  7605. already arrived. DDPRdCancel returns noErr if the DDPRead call is successfully removed
  7606. from the queue. If DDPRdCancel returns recNotFnd, check the abResult field of abRecord
  7607. to verify that the DDPRead has been completed and determine its outcome.
  7608.  
  7609. Result codes    noErr        No error
  7610.                 readQErr     Invalid socket or socket not found in table
  7611.                 recNotFnd    ABRecord not found in queue
  7612.  
  7613. »Example
  7614.  
  7615. This example sends a DDP packet synchronously and waits asynchronously for a response.
  7616. Assume that both nodes are using a known socket number (in this case, 30) to receive
  7617. packets. Normally, you would want to use NBP to look up your destination’s socket
  7618. address.
  7619.  
  7620. VAR
  7621.   myABRecord: ABRecHandle;
  7622.   myBuffer: PACKED ARRAY [0..599] OF CHAR; {buffer for both send and receive}
  7623.   mySocket: Byte;
  7624.   errCode, index, dataLen: INTEGER;
  7625.   someText: Str255;
  7626.   async, retCksumErrs, doChecksum: BOOLEAN;
  7627.  
  7628. BEGIN
  7629.   errCode := MPPOpen;
  7630.   IF errCode <> noErr THEN
  7631.     WRITELN('Error in opening AppleTalk')
  7632.     {Maybe serial port B isn't available for use by AppleTalk}
  7633.   ELSE
  7634.     BEGIN
  7635.       {Call Memory Manager to allocate ABusRecord}
  7636.       myABRecord := ABRecHandle(NewHandle(ddpSize));
  7637.       mySocket := 30;
  7638.   {Add mySocket to socket table and install default socket listener to service }
  7639. { datagrams addressed to that socket. No packets addressed to mySocket will be }
  7640.       { received until we call DDPRead. }
  7641.       errCode := DDPOpenSocket(mySocket, NIL);
  7642.       IF errCode <> noErr THEN
  7643.         WRITELN('Error while opening the socket')
  7644.       {Have we opened too many socket listeners? Remember that DDP uses two of }
  7645.         { them.}
  7646.       ELSE
  7647.         BEGIN
  7648.           {Prepare data to be sent}
  7649.           someText := 'This is a sample datagram';
  7650.           dataLen := LENGTH(someText);
  7651.           FOR index := 0 TO dataLen - 1 DO {stuff buffer with packet data}
  7652.             myBuffer[index] := someText[index + 1];
  7653.           async := FALSE;
  7654.           WITH myABRecord^^ DO {fill the parameters in the ABusRecord}
  7655.             BEGIN
  7656.               ddpType := 5;
  7657.               ddpAddress.aNet := 0; {send on “our” network}
  7658.               ddpAddress.aNode := 34;
  7659.               ddpAddress.aSocket := mySocket;
  7660.               ddpReqCount := dataLen;
  7661.               ddpDataPtr := @myBuffer;
  7662.             END;
  7663.           doChecksum := FALSE;
  7664.     {If packet contains a DDP long header, compute checksum and insert it into }
  7665.           { the header.}
  7666.           errCode := DDPWrite(myABRecord, doChecksum, async); {send packet}
  7667.      {In the case of a sync call, errCode and the abResult field of myABRecord }
  7668.    { will contain the same result code. We can also reuse myABRecord, since we }
  7669.           { know whether the call has completed.}
  7670.           IF errCode <> noErr THEN
  7671.             WRITELN('Error while writing out the packet')
  7672.             {Maybe the receiving node wasn't on-line}
  7673.           ELSE
  7674.             BEGIN
  7675.            {We have sent out the packet and are now waiting for a response. We }
  7676.            { issue an async DDPRead call so that we don't “hang” waiting for a }
  7677.           { response that may not come. To cancel the async read call, we must }
  7678.               { close the socket associated with the call or call DDPRdCancel.}
  7679.               async := TRUE;
  7680.               retCksumErrs := TRUE; {return packets even if }
  7681.                                     { they have a checksum error}
  7682.               WITH myABRecord^^ DO
  7683.                 BEGIN
  7684.                   ddpSocket := mySocket;
  7685.                   ddpReqCount := 600; {our reception buffer is max size}
  7686.                   ddpDataPtr := @myBuffer;
  7687.                 END;
  7688.               {Wait for a packet asynchronously}
  7689.               errCode := DDPRead(myABRecord, retCksumErrs, async);
  7690.               IF errCode <> noErr THEN
  7691.                 WRITELN('Error while trying to queue up a DDPRead')
  7692.                 {Was the socket listener installed correctly?}
  7693.               ELSE
  7694.                 BEGIN
  7695.                   {We can either sit here in a loop and poll the }
  7696.                   { abResult field or just exit our code and use the }
  7697.                   { event mechanism to flag us when the packet arrives.}
  7698.                   CheckForMyEvent; {your procedure for checking for a }
  7699.                                    { network event}
  7700.                   {If there were no errors, a packet is inside the array }
  7701.                   { mybuffer, the length is in ddpActCount, and the }
  7702.                   { address of the sending socket is in ddpAddress. }
  7703.                   { Process the packet received here and report any errors.}
  7704.                   errCode := DDPCloseSocket(mySocket); {we're done with it}
  7705.                   IF errCode <> noErr THEN
  7706.                     WRITELN('Error while closing the socket');
  7707.                 END;
  7708.             END;
  7709.         END;
  7710.     END;
  7711. END.
  7712.  
  7713. _______________________________________________________________________________
  7714.  
  7715. »AppleTalk Transaction Protocol
  7716.  
  7717. »Data Structures
  7718.  
  7719. ATP calls use the following ABusRecord fields:
  7720.  
  7721. atpProto:
  7722.   (atpSocket:     Byte;        {listening or responding socket number}
  7723.    atpAddress:    AddrBlock;   {destination or source socket address}
  7724.    atpReqCount:   INTEGER;     {request size or buffer size}
  7725.    atpDataPtr:    Ptr;         {pointer to buffer}
  7726.    atpRspBDSPtr:  BDSPtr;      {pointer to response BDS}
  7727.    atpBitMap:     BitMapType;  {transaction bit map}
  7728.    atpTransID:    INTEGER;     {transaction ID}
  7729.    atpActCount:   INTEGER;     {number of bytes actually received}
  7730.    atpUserData:   LONGINT;     {user bytes}
  7731.    atpXO:         BOOLEAN;     {exactly-once flag}
  7732.    atpEOM:        BOOLEAN;     {end-of-message flag}
  7733.    atpTimeOut:    Byte;        {retry timeout interval in seconds}
  7734.    atpRetries:    Byte;        {maximum number of retries}
  7735.    atpNumBufs:    Byte;        {number of elements in response BDS or number }
  7736.                                { of response packets sent}
  7737.    atpNumRsp:     Byte;        {number of response packets received or }
  7738.                                { sequence number}
  7739.    atpBDSSize:    Byte;        {number of elements in response BDS}
  7740.    atpRspUData:   LONGINT;     {user bytes sent or received in transaction }
  7741.                                { response}
  7742.    atpRspBuf:     Ptr;         {pointer to response message buffer}
  7743.    atpRspSize:    INTEGER);    {size of response message buffer}
  7744.   
  7745. The socket receiving the request or sending the response is identified by atpSocket.
  7746. ATPAddress is the address of either the destination or the source socket of a transaction,
  7747. depending on whether the call is sending or receiving data, respectively. ATPDataPtr
  7748. and atpReqCount specify the location and size
  7749. (in bytes) of a buffer that either contains a request or will receive a request. The
  7750. number of bytes actually received in a request is returned in atpActCount. ATPTransID
  7751. specifies the transaction ID. The transaction bit map is contained in atpBitMap, in
  7752. the form:
  7753.  
  7754. TYPE BitMapType = PACKED ARRAY[0..7] OF BOOLEAN;
  7755.  
  7756. Each bit in the bit map corresponds to one of the eight possible packets in a response.
  7757. For example, when a request is made for which five response packets are expected, the
  7758. bit map sent is binary 00011111 or decimal 31. If the second packet in the response
  7759. is lost, the requesting socket will retransmit the request with a bit map of binary
  7760. 00000010 or decimal 2.
  7761.  
  7762. ATPUserData contains the user bytes of an ATP header. ATPXO is TRUE if the transaction
  7763. is to be made with exactly-once service. ATPEOM is TRUE if the response packet is the
  7764. last packet of a transaction. If the number of responses is less than the number that
  7765. were requested, then ATPEOM must also be TRUE. ATPNumRsp contains either the number
  7766. of responses received or the sequence number of a response.
  7767.  
  7768. The timeout interval in seconds and the maximum number of times that a request should
  7769. be made are indicated by atpTimeOut and atpRetries, respectively.
  7770.  
  7771. Note:  Setting atpRetries to 255 will cause the request to be retransmitted
  7772.        indefinitely, until a full response is received or the call is canceled.
  7773.  
  7774. ATP provides a data structure, known as a response buffer data structure
  7775. (response BDS), for allocating buffer space to receive the datagram(s) of the response.
  7776. A response BDS is an array of one to eight elements. Each BDS element defines the
  7777. size and location of a buffer for receiving one response datagram; they’re numbered 0
  7778. to 7 to correspond to the sequence numbers of the response datagrams.
  7779.  
  7780. ATP needs a separate buffer for each response datagram expected, since packets may
  7781. not arrive in the proper sequence. It does not, however, require you to set up and
  7782. use the BDS data structure to describe the response buffers; if you
  7783. don’t, ATP will do it for you. Two sets of calls are provided for both requests and
  7784. responses; one set requires you to allocate a response BDS and the other doesn’t.
  7785.  
  7786. Assembly-language note:  The two calls that don’t require you to define a BDS
  7787.                          data structure (ATPRequest and ATPResponse) are
  7788.                          available in Pascal only.
  7789.  
  7790. The number of BDS elements allocated (in other words, the maximum number of datagrams
  7791. that the responder can send) is indicated in the TReq by an eight-bit bit map. The
  7792. bits of this bit map are numbered 0 to 7 (the least significant bit being number 0);
  7793. each bit corresponds to the response datagram with the respective sequence number.
  7794.  
  7795. ATPRspBDSPtr and atpBDSSize indicate the location and number of elements in the
  7796. response BDS, which has the following structure:
  7797.  
  7798. TYPE  BDSElement =
  7799.              RECORD
  7800.                buffSize:   INTEGER;  {buffer size in bytes}
  7801.                buffPtr:    Ptr;      {pointer to buffer}
  7802.                dataSize:   INTEGER;  {number of bytes actually received}
  7803.                userBytes:  LONGINT   {user bytes}
  7804.              END;
  7805.  
  7806.       BDSType = ARRAY[0..7] OF BDSElement; {response BDS}
  7807.       BDSPtr  = ^BDSType;
  7808.  
  7809. ATPNumBufs indicates the number of elements in the response BDS that contain information.
  7810. In most cases, you can allocate space for your variables of BDSType statically with a
  7811. VAR declaration. However, you can allocate only the minimum space required by your
  7812. ATP calls by doing the following:
  7813.  
  7814.   VAR myBDSPtr:  BDSPtr;
  7815.       . . .
  7816.   numOfBDS := 3; {number of elements needed}
  7817.   myBDSPtr := BDSPtr(NewPtr(SIZEOF(BDSElement) * numOfBDS));
  7818.  
  7819. Note:  The userBytes field of the BDSElement and the atpUserData field
  7820.        of the ABusRecord represent the same information in the datagram.
  7821.        Depending on the ATP call made, one or both of these fields will be used.
  7822.  
  7823. »Using ATP
  7824.  
  7825. Before you can use ATP on a Macintosh 128K, the .ATP driver must be read from the
  7826. system resource file via an ATPLoad call. The .ATP driver loads itself into the
  7827. application heap and installs a task into the vertical retrace queue.
  7828.  
  7829. Warning:  When another application starts up, the application heap is
  7830.           reinitialized; on a Macintosh 128K, this means that the ATP
  7831.           code is lost (and must be reloaded by the next application).
  7832.  
  7833. When you’re through using ATP on a Macintosh 128K, call ATPUnload—the system will be
  7834. returned to the state it was in before the .ATP driver was opened.
  7835.  
  7836. On a Macintosh 512K or XL, the .ATP driver will have been loaded into the system heap
  7837. either at system startup or upon execution of MPPOpen or ATPLoad. ATPUnload has no
  7838. effect on a Macintosh 512K or XL.
  7839.  
  7840. To send a transaction request, call ATPSndRequest or ATPRequest. The .ATP driver will
  7841. automatically select and open a socket through which the request datagram will be
  7842. sent, and through which the response datagrams will be received. The requester must
  7843. specify the full network address (network number, node ID, and socket number) of the
  7844. socket to which the request is to be sent. This socket is known as the responding
  7845. socket, and its address must be known in advance by the requester.
  7846.  
  7847. At the responder’s end, before a transaction request can be received, a responding
  7848. socket must be opened, and the appropriate calls be made, to receive a request. To do
  7849. this, the responder first makes an ATPOpenSocket call which allows the responder to
  7850. specify the address (or part of it) of the requesters from whom it’s willing to
  7851. accept transaction requests. Then it issues an ATPGetRequest call to provide ATP with
  7852. a buffer for receiving a request; when a request is received, ATPGetRequest is completed.
  7853. The responder can queue up several ATPGetRequest calls, each of which will be completed
  7854. as requests are received.
  7855.  
  7856. Upon receiving a request, the responder performs the requested operation, and then
  7857. prepares the information to be returned to the requester. It then calls ATPSndRsp (or
  7858. ATPResponse) to send the response. Actually, the responder can issue the ATPSndRsp
  7859. call with only part (or none) of the response specified. Additional portions of the
  7860. response can be sent later by calling ATPAddRsp.
  7861.  
  7862. The ATPSndRsp and ATPAddRsp calls provide flexibility in the design (and range of
  7863. types) of transaction responders. For instance, the responder may, for some reason,
  7864. be forced to send the responses out of sequence. Also, there might be memory constraints
  7865. that force sending the complete transaction response in parts. Even though eight
  7866. response datagrams might need to be sent, the responder might have only enough memory
  7867. to build one datagram at a time. In this case, it would build the first response
  7868. datagram and call ATPSndRsp to send it. It would then build the second response
  7869. datagram in the same buffer and call ATPAddRsp to send it; and so on, for the third
  7870. through eighth response datagrams.
  7871.  
  7872. A responder can close a responding socket by calling ATPCloseSocket. This call cancels
  7873. all pending ATP calls for that socket, such as ATPGetRequest, ATPSndRsp, and ATPResponse.
  7874.  
  7875. For exactly-once transactions, the ATPSndRsp and ATPAddRsp calls don’t terminate
  7876. until the entire transaction has completed (that is, the responding end receives a
  7877. release packet, or the release timer has expired).
  7878.  
  7879. To cancel a pending, asynchronous ATPSndRequest or ATPRequest call, call ATPReqCancel.
  7880. To cancel a pending, asynchronous ATPSndRsp or ATPResponse call, call ATPRspCancel.
  7881. Pending asynchronous ATPGetRequest calls can be canceled only by issuing the ATPCloseSocket
  7882. call, but that will cancel all outstanding calls for that socket.
  7883.  
  7884. •••Refer to Technical Note #250:•••
  7885.  
  7886. Warning:  You cannot reuse a variable of type ABusRecord passed to an ATP
  7887.           routine until the entire transaction has either been completed
  7888.           or canceled.
  7889.  
  7890. »ATP Routines
  7891.  
  7892. FUNCTION ATPLoad :  OSErr; [Not in ROM]
  7893.  
  7894. •••Refer to Technical Note #224:•••
  7895.  
  7896. ATPLoad first verifies that the .MPP driver is loaded and running. If it isn’t,
  7897. ATPLoad verifies that port B is configured for AppleTalk and isn’t in use, and then
  7898. loads MPP into the system heap.
  7899.  
  7900. ATPLoad then loads the .ATP driver, unless it’s already in memory. On a Macintosh
  7901. 128K, ATPLoad reads the .ATP driver from the system resource file into the application
  7902. heap; on a Macintosh 512K or XL, ATP is read into the system heap.
  7903.  
  7904. Note:  On a Macintosh 512K or XL, ATPLoad and MPPOpen perform essentially
  7905.        the same function.
  7906.  
  7907. Result codes    noErr        No error
  7908.                 portInUse    Port B is already in use
  7909.                 portNotCf    Port B not configured for AppleTalk
  7910.  
  7911. FUNCTION ATPUnload :  OSErr; [Not in ROM]
  7912.  
  7913. ATPUnload makes the .ATP driver purgeable; the space isn’t actually released by the
  7914. Memory Manager until necessary.
  7915.  
  7916. Note:  This call applies only to a Macintosh 128K; on a Macintosh 512K
  7917.        or Macintosh XL, ATPUnload has no effect.
  7918.  
  7919. Result codes    noErr    No error
  7920.  
  7921. FUNCTION ATPOpenSocket (addrRcvd:  AddrBlock;
  7922.                         VAR atpSocket:  Byte) :  OSErr; [Not in ROM]
  7923.  
  7924. ATPOpenSocket opens a socket for the purpose of receiving requests. ATPSocket contains
  7925. the socket number of the socket to open; if it’s 0, a number is dynamically assigned
  7926. and returned in atpSocket. AddrRcvd contains a filter of the sockets from which
  7927. requests will be accepted. A 0 in the network number, node ID, or socket number field
  7928. of the addrRcvd record acts as a “wild card”; for instance, a 0 in the socket number
  7929. field means that requests will be accepted from all sockets in the node(s) specified
  7930. by the network and node fields.
  7931.  
  7932. Result codes    noErr          No error
  7933.                 tooManySkts    Socket table full
  7934.                 noDataArea     Too many outstanding ATP calls
  7935.  
  7936. Note:  If you’re only going to send requests and receive responses to
  7937.        these requests, you don’t need to open an ATP socket. When you
  7938.        make the ATPSndRequest or ATPRequest call, ATP automatically
  7939.        opens a dynamically assigned socket for that purpose.
  7940.  
  7941. FUNCTION ATPCloseSocket (atpSocket:  Byte) :  OSErr; [Not in ROM]
  7942.  
  7943. ATPCloseSocket closes the responding socket whose number is specified by atpSocket.
  7944. It releases the data structures associated with all pending, asynchronous calls
  7945. involving that socket; these pending calls are completed immediately and return the
  7946. result code sktClosed.
  7947.  
  7948. Result codes    noErr         No error
  7949.                 noDataArea    Too many outstanding ATP calls
  7950.  
  7951. FUNCTION ATPSndRequest (abRecord:  ABRecHandle;
  7952.                         async:  BOOLEAN) :  OSErr; [Not in ROM]
  7953.  
  7954. ABusRecord
  7955.   <--    abOpcode         {always tATPSndRequest}
  7956.   <--    abResult         {result code}
  7957.   -->    abUserReference  {for your use}
  7958.   -->    atpAddress       {destination socket address}
  7959.   -->    atpReqCount      {request size in bytes}
  7960.   -->    atpDataPtr       {pointer to buffer}
  7961.   -->    atpRspBDSPtr     {pointer to response BDS}
  7962.   -->    atpUserData      {user bytes}
  7963.   -->    atpXO            {exactly-once flag}
  7964.   <--    atpEOM           {end-of-message flag}
  7965.   -->    atpTimeOut       {retry timeout interval in seconds}
  7966.   -->    atpRetries       {maximum number of retries}
  7967.   -->    atpNumBufs       {number of elements in response BDS}
  7968.   <--    atpNumRsp        {number of response packets actually received}
  7969.  
  7970. ATPSndRequest sends a request to another socket. ATPAddress is the internet address
  7971. of the socket to which the request should be sent. ATPDataPtr and atpReqCount specify
  7972. the location and size of a buffer that contains the request information to be sent.
  7973. ATPUserData contains the user bytes for the ATP header.
  7974.  
  7975. ATPSndRequest requires you to allocate a response BDS. ATPRspBDSPtr is a pointer to
  7976. the response BDS; atpNumBufs indicates the number of elements in the BDS (this is
  7977. also the maximum number of response datagrams that will be accepted). The number of
  7978. response datagrams actually received is returned in atpNumRsp; if a nonzero value is
  7979. returned, you can examine the response BDS to determine which packets of the transaction
  7980. were actually received. If the number returned is less than requested, one of the
  7981. following is true:
  7982.  
  7983.   •  Some of the packets have been lost and the retry count has been exceeded.
  7984.   •  ATPEOM is TRUE; this means that the response consisted of fewer packets
  7985.      than were expected, but that all packets sent were received (the last
  7986.      packet came with the atpEOM flag set).
  7987.  
  7988. ATPTimeOut indicates the length of time that ATPSndRequest should wait for a response
  7989. before retransmitting the request. ATPRetries indicates the maximum number of retries
  7990. ATPSndRequest should attempt. ATPXO should be TRUE if you want the request to be part
  7991. of an exactly-once transaction.
  7992.  
  7993. ATPSndRequest completes when either the transaction is completed or the retry count
  7994. is exceeded.
  7995.  
  7996. Result codes    noErr          No error
  7997.                 reqFailed      Retry count exceeded
  7998.                 tooManyReqs    Too many concurrent requests
  7999.                 noDataArea     Too many outstanding ATP calls
  8000.  
  8001. FUNCTION ATPRequest (abRecord:  ABRecHandle;
  8002.                      async:  BOOLEAN) :  OSErr; [Not in ROM]
  8003.  
  8004. ABusRecord
  8005.   <--    abOpcode         {always tATPRequest}
  8006.   <--    abResult         {result code}
  8007.   -->    abUserReference  {for your use}
  8008.   -->    atpAddress       {destination socket address}
  8009.   -->    atpReqCount      {request size in bytes}
  8010.   -->    atpDataPtr       {pointer to buffer}
  8011.   <--    atpActCount      {number of bytes actually received}
  8012.   -->    atpUserData      {user bytes}
  8013.   -->    atpXO            {exactly-once flag}
  8014.   <--    atpEOM           {end-of-message flag}
  8015.   -->    atpTimeOut       {retry timeout interval in seconds}
  8016.   -->    atpRetries       {maximum number of retries}
  8017.   <--    atpRspUData      {user bytes received in transaction response}
  8018.   -->    atpRspBuf        {pointer to response message buffer}
  8019.   -->    atpRspSize       {size of response message buffer}
  8020.  
  8021. ATPRequest is functionally analogous to ATPSndRequest. It sends a request to another
  8022. socket, but doesn’t require the caller to set up and use the BDS data structure to
  8023. describe the response buffers. ATPAddress indicates the socket to which the request
  8024. should be sent. ATPDataPtr and atpReqCount specify the location and size of a buffer
  8025. that contains the request information to be sent. ATPUserData contains the user bytes
  8026. to be sent in the request’s ATP header. ATPTimeOut indicates the length of time that
  8027. ATPRequest should wait for a response before retransmitting the request. ATPRetries
  8028. indicates the maximum number of retries ATPRequest should attempt.
  8029.  
  8030. To use this call, you must have an area of contiguous buffer space that’s large
  8031. enough to receive all expected datagrams. The various datagrams will be assembled in
  8032. this buffer and returned to you as a complete message upon completion of the transaction.
  8033. The location and size of this buffer are passed in atpRspBuf and atpRspSize. Upon
  8034. completion of the call, the size of the received response message is returned in
  8035. atpActCount. The user bytes received in the ATP header of the first response packet
  8036. are returned in atpRspUData. ATPXO should be TRUE if you want the request to be part
  8037. of an exactly-once transaction.
  8038.  
  8039. Although you don’t provide a BDS, ATPRequest in fact creates one and calls the
  8040. .ATP driver (as in an ATPSndRequest call). For this reason, the abRecord fields
  8041. atpRspBDSPtr and atpNumBufs are used by ATPRequest; you should not expect these
  8042. fields to remain unaltered during or after the function’s execution.
  8043.  
  8044. For ATPRequest to receive and correctly deliver the response as a single message, the
  8045. responding end must, upon receiving the request (with an ATPGetRequest call), generate
  8046. the complete response as a message in a single buffer and then call ATPResponse.
  8047.  
  8048. Note:  The responding end could also use ATPSndRsp and ATPAddRsp provided
  8049.        that each response packet (except the last one) contains exactly 578
  8050.        ATP data bytes; the last packet in the response can contain less than
  8051.        578 ATP data bytes. Also, if this method is used, only the ATP user
  8052.        bytes of the first response packet will be delivered to the requester;
  8053.        any information in the user bytes of the remaining response packets
  8054.        will not be delivered.
  8055.  
  8056. ATPRequest completes when either the transaction is completed or the retry count is
  8057. exceeded.
  8058.  
  8059. Result codes    noErr          No error
  8060.                 reqFailed      Retry count exceeded
  8061.                 tooManyReqs    Too many concurrent requests
  8062.                 sktClosed      Socket closed by a cancel call
  8063.                 noDataArea     Too many outstanding ATP calls
  8064.  
  8065. FUNCTION ATPReqCancel (abRecord:  ABRecHandle;
  8066.                        async:  BOOLEAN) :  OSErr; [Not in ROM]
  8067.  
  8068. Given the handle to the ABusRecord of a previously made ATPSndRequest or ATPRequest
  8069. call, ATPReqCancel dequeues the ATPSndRequest or ATPRequest call, provided that the
  8070. call hasn’t already completed. ATPReqCancel returns noErr if the ATPSndRequest or
  8071. ATPRequest call is successfully removed from the queue. If it returns cbNotFound,
  8072. check the abResult field of abRecord to verify that the ATPSndRequest or ATPRequest
  8073. call has completed and determine its outcome.
  8074.  
  8075. Result codes    noErr         No error
  8076.                 cbNotFound    ATP control block not found
  8077.  
  8078. FUNCTION ATPGetRequest (abRecord:  ABRecHandle;
  8079.                         async:  BOOLEAN) :  OSErr; [Not in ROM]
  8080.  
  8081. ABusRecord
  8082.   <--    abOpcode         {always tATPGetRequest}
  8083.   <--    abResult         {result code}
  8084.   -->    abUserReference  {for your use}
  8085.   -->    atpSocket        {listening socket number}
  8086.   <--    atpAddress       {source socket address}
  8087.   -->    atpReqCount      {buffer size in bytes}
  8088.   -->    atpDataPtr       {pointer to buffer}
  8089.   <--    atpBitMap        {transaction bit map}
  8090.   <--    atpTransID       {transaction ID}
  8091.   <--    atpActCount      {number of bytes actually received}
  8092.   <--    atpUserData      {user bytes}
  8093.   <--    atpXO            {exactly-once flag}
  8094.  
  8095. ATPGetRequest sets up the mechanism to receive a request sent by either an ATPSndRequest
  8096. or an ATPRequest call. ATPSocket contains the socket number of the socket that should
  8097. listen for a request; this socket must already have been opened by calling ATPOpenSocket.
  8098. The address of the socket from which the request was sent is returned in atpAddress.
  8099. ATPDataPtr specifies a buffer to store the incoming request; atpReqCount indicates
  8100. the size of the buffer in bytes. The number of bytes actually received in the request
  8101. is returned in atpActCount. ATPUserData contains the user bytes from the ATP header.
  8102. The transaction bit map is returned in atpBitMap. The transaction ID is returned in
  8103. atpTransID. ATPXO will be TRUE if the request is part of an exactly-once transaction.
  8104.  
  8105. ATPGetRequest completes when a request is received. To cancel an asynchronous ATPGetRequest
  8106. call, you must call ATPCloseSocket, but this cancels all pending calls involving that
  8107. socket.
  8108.  
  8109. Result codes    noErr        No error
  8110.                 badATPSkt    Bad responding socket
  8111.                 sktClosed    Socket closed by a cancel call
  8112.  
  8113. FUNCTION ATPSndRsp (abRecord:  ABRecHandle;
  8114.                     async:  BOOLEAN) :  OSErr; [Not in ROM]
  8115.  
  8116. ABusRecord
  8117.   <--    abOpcode         {always tATPSdRsp}
  8118.   <--    abResult         {result code}
  8119.   -->    abUserReference  {for your use}
  8120.   -->    atpSocket        {responding socket number}
  8121.   -->    atpAddress       {destination socket address}
  8122.   -->    atpRspBDSPtr     {pointer to response BDS}
  8123.   -->    atpTransID       {transaction ID}
  8124.   -->    atpEOM           {end-of-message flag}
  8125.   -->    atpNumBufs       {number of response packets being sent}
  8126.   -->    atpBDSSize       {number of elements in response BDS}
  8127.  
  8128. ATPSndRsp sends a response to another socket. ATPSocket contains the socket number
  8129. from which the response should be sent and atpAddress contains the internet address
  8130. of the socket to which the response should be sent. ATPTransID must contain the
  8131. transaction ID. ATPEOM is TRUE if the response BDS contains the final packet in a
  8132. transaction composed of a group of packets and the number of packets in the response
  8133. is less than expected. ATPRspBDSPtr points to the buffer data structure containing
  8134. the responses to be sent. ATPBDSSize indicates the number of elements in the response
  8135. BDS, and must be in the range 1 to 8. ATPNumBufs indicates the number of response
  8136. packets being sent with this call, and must be in the range 0 to 8.
  8137.  
  8138. Note:  In some situations, you may want to send only part (or possibly none)
  8139.        of your response message back immediately. For instance, you might be
  8140.        requested to send back seven disk blocks, but have only enough internal
  8141.        memory to store one block. In this case, set atpBDSSize to 7 (total
  8142.        number of response packets), atpNumBufs to 0 (number of response
  8143.        packets currently being sent), and call ATPSndRsp. Then as you read
  8144.        in one block at a time, call ATPAddRsp until all seven response
  8145.        datagrams have been sent.
  8146.  
  8147. During exactly-once transactions, ATPSndRsp won’t complete until the release packet
  8148. is received or the release timer expires.
  8149.  
  8150. Result codes    noErr         No error
  8151.                 badATPSkt     Bad responding socket
  8152.                 noRelErr      No release received
  8153.                 sktClosed     Socket closed by a cancel call
  8154.                 noDataArea    Too many outstanding ATP calls
  8155.                 badBuffNum    Bad sequence number
  8156.  
  8157. FUNCTION ATPAddRsp (abRecord:  ABRecHandle) :  OSErr; [Not in ROM]
  8158.  
  8159. ABusRecord
  8160.   <--    abOpcode         {always tATPAddRsp}
  8161.   <--    abResult         {result code}
  8162.   -->    abUserReference  {for your use}
  8163.   -->    atpSocket        {responding socket number}
  8164.   -->    atpAddress       {destination socket address}
  8165.   -->    atpReqCount      {buffer size in bytes}
  8166.   -->    atpDataPtr       {pointer to buffer}
  8167.   -->    atpTransID       {transaction ID}
  8168.   -->    atpUserData      {user bytes}
  8169.   -->    atpEOM           {end-of-message flag}
  8170.   -->    atpNumRsp        {sequence number}
  8171.  
  8172. ATPAddRsp sends one additional response packet to a socket that has already been sent
  8173. the initial part of a response via ATPSndRsp. ATPSocket contains the socket number
  8174. from which the response should be sent and atpAddress contains the internet address
  8175. of the socket to which the response should be sent. ATPTransID must contain the
  8176. transaction ID. ATPDataPtr and atpReqCount specify the location and size of a buffer
  8177. that contains the information to send; atpNumRsp is the sequence number of the response.
  8178. ATPEOM is TRUE if this response datagram is the final packet in a transaction composed
  8179. of a group of packets. ATPUserData contains the user bytes to be sent in this response
  8180. datagram’s ATP header.
  8181.  
  8182. Note:  No BDS is needed with ATPAddRsp because all pertinent information
  8183.        is passed within the record.
  8184.  
  8185. Result codes    noErr         No error
  8186.                 badATPSkt     Bad responding socket
  8187.                 badBuffNum    Bad sequence number
  8188.                 noSendResp    ATPAddRsp issued before ATPSndRsp
  8189.                 noDataArea    Too many outstanding ATP calls
  8190.  
  8191. FUNCTION ATPResponse (abRecord:  ABRecHandle;
  8192.                       async:  BOOLEAN) :  OSErr; [Not in ROM]
  8193.  
  8194. ABusRecord
  8195.   <--    abOpcode         {always tATPResponse}
  8196.   <--    abResult         {result code}
  8197.   -->    abUserReference  {for your use}
  8198.   -->    atpSocket        {responding socket number}
  8199.   -->    atpAddress       {destination socket address}
  8200.   -->    atpTransID       {transaction ID)
  8201.   -->    atpRspUData      {user bytes sent in transaction response}
  8202.   -->    atpRspBuf        {pointer to response message buffer}
  8203.   -->    atpRspSize       {size of response message buffer}
  8204.  
  8205. ATPResponse is functionally analogous to ATPSndRsp. It sends a response to another
  8206. socket, but doesn’t require the caller to provide a BDS. ATPAddress must contain the
  8207. complete network address of the socket to which the response should be sent (taken
  8208. from the data provided by an ATPGetRequest call). ATPTransID must contain the transaction
  8209. ID. ATPSocket indicates the socket from which the response should be sent (the socket
  8210. on which the corresponding ATPGetRequest was issued). ATPRspBuf points to the buffer
  8211. containing the response message; the size of this buffer must be passed in atpRspSize.
  8212. The four user bytes to be sent in the ATP header of the first response packet are
  8213. passed in atpRspUData. The last packet of the transaction response is sent with the
  8214. EOM flag set.
  8215.  
  8216. Although you don’t provide a BDS, ATPResponse in fact creates one and calls the .ATP
  8217. driver (as in an ATPSndRsp call). For this reason, the abRecord fields atpRspBDSPtr
  8218. and atpNumBufs are used by ATPResponse; you should not expect these fields to remain
  8219. unaltered during or after the function’s execution.
  8220.  
  8221. During exactly-once transactions ATPResponse won’t complete until the release packet
  8222. is received or the release timer expires.
  8223.  
  8224. Warning:  The maximum permissible size of the response message is 4624 bytes.
  8225.  
  8226. Result codes    noErr         No error
  8227.                 badATPSkt     Bad responding socket
  8228.                 noRelErr      No release received
  8229.                 atpLenErr     Response too big
  8230.                 sktClosed     Socket closed by a cancel call
  8231.                 noDataArea    Too many outstanding ATP calls
  8232.  
  8233. FUNCTION ATPRspCancel (abRecord:  ABRecHandle;
  8234.                        async:  BOOLEAN) :  OSErr; [Not in ROM]
  8235.  
  8236. Given the handle to the ABusRecord of a previously made ATPSndRsp or ATPResponse
  8237. call, ATPRspCancel dequeues the ATPSndRsp or ATPResponse call, provided that the call
  8238. hasn’t already completed. ATPRspCancel returns noErr if the ATPSndRsp or ATPResponse
  8239. call is successfully removed from the queue. If it returns cbNotFound, check the
  8240. abResult field of abRecord to verify that the ATPSndRsp or ATPResponse call has
  8241. completed and determine its outcome.
  8242.  
  8243. Result codes    noErr         No error
  8244.                 cbNotFound    ATP control block not found
  8245.  
  8246. »Example
  8247.  
  8248. This example shows the requesting side of an ATP transaction that asks for a 512-byte
  8249. disk block from the responding end. The block number of the file is a byte and is
  8250. contained in myBuffer[0].
  8251.  
  8252. VAR
  8253.   myABRecord: ABRecHandle;
  8254.   myBDSPtr: BDSPtr;
  8255.   myBuffer: PACKED ARRAY [0..511] OF CHAR;
  8256.   errCode: INTEGER;
  8257.   async: BOOLEAN;
  8258.  
  8259. BEGIN
  8260.   errCode := ATPLoad;
  8261.   IF errCode <> noErr THEN
  8262.     WRITELN('Error in opening AppleTalk')
  8263.     {Maybe serial port B isn't available for use by AppleTalk}
  8264.   ELSE
  8265.     BEGIN
  8266.       {Prepare the BDS; allocate space for a one-element BDS}
  8267.       myBDSPtr := BDSPtr(NewPtr(SIZEOF(BDSElement)));
  8268.       WITH myBDSPtr^[0] DO
  8269.         BEGIN
  8270.           buffSize := 512; {size of our buffer used in reception}
  8271.           buffPtr := @myBuffer; {pointer to the buffer}
  8272.         END;
  8273.       {Prepare the ABusRecord}
  8274.       myBuffer[0] := CHR(1); {requesting disk block number 1}
  8275.       myABRecord := ABRecHandle(NewHandle(atpSize));
  8276.       WITH myABRecord^^ DO
  8277.         BEGIN
  8278.           atpAddress.aNet := 0;
  8279.           atpAddress.aNode := 30; {we probably got this from an NBP call}
  8280.           atpAddress.aSocket := 15; {socket to send request to}
  8281.           atpReqCount := 1; {size of request data field (disk block #)}
  8282.           atpDataPtr := @myBuffer; {ptr to request to be sent}
  8283.           atpRspBDSPtr := @myBDSPtr;
  8284.           atpUserData := 0; {for your use}
  8285.           atpXO := FALSE; {at-least-once service}
  8286.           atpTimeOut := 5; {5-second timeout}
  8287.           atpRetries := 3; {3 retries; request will be sent 4 times max}
  8288.           atpNumBufs := 1; {we're only expecting 1 block to be returned}
  8289.         END;
  8290.       async := FALSE;
  8291.       {Send the request and wait for the response}
  8292.       errCode := ATPSndRequest(myABRecord, async);
  8293.       IF errCode <> noErr THEN
  8294.         WRITELN('An error occurred in the ATPSndRequest call')
  8295.       ELSE
  8296.         BEGIN
  8297.           {The disk block requested is now in myBuffer. We can verify }
  8298.           { that atpNumRsp contains 1, meaning one response received.}
  8299.         . . .
  8300.         END;
  8301.     END;
  8302. END.
  8303.  
  8304. _______________________________________________________________________________
  8305.  
  8306. »Name-Binding Protocol
  8307.  
  8308. »Data Structures
  8309.  
  8310. NBP calls use the following fields:
  8311.  
  8312. nbpProto:
  8313.   (nbpEntityPtr:       EntityPtr;     {pointer to entity name}
  8314.    nbpBufPtr:          Ptr;           {pointer to buffer}
  8315.    nbpBufSize:         INTEGER;       {buffer size in bytes}
  8316.    nbpDataField:       INTEGER;       {number of addresses or socket number}
  8317.    nbpAddress:         AddrBlock;     {socket address}
  8318.    nbpRetransmitInfo:  RetransType);  {retransmission information}
  8319.  
  8320. When data is sent via NBP, nbpBufSize indicates the size of the data in bytes and
  8321. nbpBufPtr points to a buffer containing the data. When data is received via NBP,
  8322. nbpBufPtr points to a buffer in which the incoming data can be stored and nbpBufSize
  8323. indicates the size of the buffer in bytes. NBPAddress is used in some calls to give
  8324. the internet address of a named entity. The AddrBlock data type is described above
  8325. under “Datagram Delivery Protocol”.
  8326.  
  8327. NBPEntityPtr points to a variable of type EntityName, which has the following data
  8328. structure:
  8329.  
  8330. TYPE  EntityName = RECORD
  8331.                      objStr:   Str32;   {object}
  8332.                      typeStr:  Str32;   {type}
  8333.                      zoneStr:  Str32    {zone}
  8334.                    END;
  8335.  
  8336.       EntityPtr = ^EntityName;
  8337.       Str32 = STRING[32];
  8338.  
  8339. NBPRetransmitInfo contains information about the number of times a packet should be
  8340. transmitted and the interval between retransmissions:
  8341.  
  8342. TYPE  RetransType =  PACKED RECORD
  8343.                        retransInterval:  Byte;    {retransmit interval in }
  8344.                                                   { 8-tick units}
  8345.                        retransCount:     Byte     {total number of attempts}
  8346.                      END;
  8347.  
  8348. RetransCount contains the total number of times a packet should be transmitted,
  8349. including the first transmission. If retransCount is 0, the packet will be transmitted
  8350. a total of 255 times.
  8351.  
  8352. »Using NBP
  8353.  
  8354. On a Macintosh 128K, the AppleTalk Manager’s NBP code is read into the application
  8355. heap when any one of the NBP (Pascal) routines is called; you can call the NBPLoad
  8356. function yourself if you want to load the NBP code explicitly. When you’re finished
  8357. with the NBP code and want to reclaim the space it occupies, call NBPUnload. On a
  8358. Macintosh 512K or XL, the NBP code is read in when the .MPP driver is loaded.
  8359.  
  8360. Note:  When another application starts up, the application heap is
  8361.        reinitialized; on a Macintosh 128K, this means that the NBP
  8362.        code is lost (and must be reloaded by the next application).
  8363.  
  8364. When an entity wants to communicate via an AppleTalk network, it should call NBPRegister
  8365. to place its name and internet address in the names table. When an entity no longer
  8366. wants to communicate on the network, or is being shut down, it should call NBPRemove
  8367. to remove its entry from the names table.
  8368.  
  8369. To determine the address of an entity you know only by name, call NBPLookup, which
  8370. returns a list of all entities with the name you specify. Call NBPExtract to extract
  8371. entity names from the list.
  8372.  
  8373. If you already know the address of an entity, and want only to confirm that it still
  8374. exists, call NBPConfirm. NBPConfirm is more efficient than NBPLookup in terms of
  8375. network traffic.
  8376.  
  8377. »NBP Routines
  8378.  
  8379. FUNCTION NBPRegister (abRecord:  ABRecHandle;
  8380.                       async:  BOOLEAN) :  OSErr; [Not in ROM]
  8381.  
  8382. ABusRecord
  8383.   <--    abOpcode            {always tNBPRegister}
  8384.   <--    abResult            {result code}
  8385.   -->    abUserReference     {for your use}
  8386.   -->    nbpEntityPtr        {pointer to entity name}
  8387.   -->    nbpBufPtr           {pointer to buffer}
  8388.   -->    nbpBufSize          {buffer size in bytes}
  8389.   -->    nbpAddress.aSocket  {socket address}
  8390.   -->    nbpRetransmitInfo   {retransmission information}
  8391.  
  8392. NBPRegister adds the name and address of an entity to the node’s names table. NBPEntityPtr
  8393. points to a variable of type EntityName containing the entity’s name. If the name is
  8394. already registered, NBPRegister returns the result code nbpDuplicate. NBPAddress
  8395. indicates the socket for which the name should be registered. NBPBufPtr and nbpBufSize
  8396. specify the location and size of a buffer for NBP to use internally.
  8397.  
  8398. While the variable of type EntityName is declared as three 32-byte strings, only the
  8399. actual characters of the name are placed in the buffer pointed to by nbpBufPtr. For
  8400. this reason, nbpBufSize needs only to be equal to the actual length of the name, plus
  8401. an additional 12 bytes for use by NBP.
  8402.  
  8403. Warning:  This buffer must not be altered or released until the name is
  8404.           removed from the names table via an NBPRemove call. If you
  8405.           allocate the buffer through a NewHandle call, you must lock
  8406.           it as long as the name is registered.
  8407.  
  8408. Warning:  The zone field of the entity name must be set to the
  8409.           meta-character “*”.
  8410.  
  8411. Result codes    noErr           No error
  8412.                 nbpDuplicate    Duplicate name already exists
  8413.  
  8414. FUNCTION NBPLookup (abRecord:  ABRecHandle;
  8415.                     async:  BOOLEAN) :  OSErr; [Not in ROM]
  8416.  
  8417. ABusRecord
  8418.   <--    abOpcode           {always tNBPLookup}
  8419.   <--    abResult           {result code}
  8420.   -->    abUserReference    {for your use}
  8421.   -->    nbpEntityPtr       {pointer to entity name}
  8422.   -->    nbpBufPtr          {pointer to buffer}
  8423.   -->    nbpBufSize         {buffer size in bytes}
  8424.   <->    nbpDataField       {number of addresses received}
  8425.   -->    nbpRetransmitInfo  {retransmission information}
  8426.  
  8427. NBPLookup returns the addresses of all entities with a specified name. NBPEntityPtr
  8428. points to a variable of type EntityName containing the name of the entity whose
  8429. address should be returned. (Meta-characters are allowed in the entity name.) NBPBufPtr
  8430. and nbpBufSize contain the location and size of an area of memory in which the entity
  8431. names and their corresponding addresses should be returned. NBPDataField indicates
  8432. the maximum number of matching names to find addresses for; the actual number of
  8433. addresses found is returned in nbpDataField. NBPRetransmitInfo contains the retry
  8434. interval and the retry count.
  8435.  
  8436. When specifying nbpBufSize, for each NBP tuple expected, allow space for the actual
  8437. characters of the name, the address, and four bytes for use by NBP.
  8438.  
  8439. Result codes    noErr         No error
  8440.                 nbpBuffOvr    Buffer overflow
  8441.  
  8442. FUNCTION NBPExtract (theBuffer:  Ptr; numInBuf:  INTEGER; whichOne:  INTEGER;
  8443.                      VAR abEntity:  EntityName;
  8444.                      VAR address:  AddrBlock) :  OSErr; [Not in ROM]
  8445.  
  8446. NBPExtract returns one address from the list of addresses returned by NBPLookup.
  8447. TheBuffer and numInBuf indicate the location and number of tuples in the buffer.
  8448. WhichOne specifies which one of the tuples in the buffer should be returned in the
  8449. abEntity and address parameters.
  8450.  
  8451. Result codes    noErr         No error
  8452.                 extractErr    Can’t find tuple in buffer
  8453.  
  8454. FUNCTION NBPConfirm (abRecord:  ABRecHandle;
  8455.                      async:  BOOLEAN) :  OSErr; [Not in ROM]
  8456.  
  8457. ABusRecord
  8458.   <--    abOpcode           {always tNBPConfirm}
  8459.   <--    abResult           {result code}
  8460.   -->    abUserReference    {for your use}
  8461.   -->    nbpEntityPtr       {pointer to entity name}
  8462.   <--    nbpDataField       {socket number}
  8463.   -->    nbpAddress         {socket address}
  8464.   -->    nbpRetransmitInfo  {retransmission information}
  8465.  
  8466. NBPConfirm confirms that an entity known by name and address still exists (is still
  8467. entered in the names directory). NBPEntityPtr points to a variable of type EntityName
  8468. that contains the name to confirm, and nbpAddress specifies the address to be confirmed.
  8469. (No meta-characters are allowed in the entity name.) NBPRetransmitInfo contains the
  8470. retry interval and the retry count. The socket number of the entity is returned in
  8471. nbpDataField. NBPConfirm is more efficient than NBPLookup in terms of network traffic.
  8472.  
  8473. Result codes    noErr           No error
  8474.                 nbpConfDiff     Name confirmed for different socket
  8475.                 nbpNoConfirm    Name not confirmed
  8476.  
  8477. FUNCTION NBPRemove (abEntity:  EntityPtr) :  OSErr; [Not in ROM]
  8478.  
  8479. NBPRemove removes an entity name from the names table of the given entity’s node.
  8480.  
  8481. Result codes    noErr          No error
  8482.                 nbpNotFound    Name not found
  8483.  
  8484. FUNCTION NBPLoad :  OSErr; [Not in ROM]
  8485.  
  8486. On a Macintosh 128K, NBPLoad reads the NBP code from the system resource file into
  8487. the application heap. On a Macintosh 512K or XL, NBPLoad has no effect since the NBP
  8488. code should have already been loaded when the .MPP driver was opened. Normally you’ll
  8489. never need to call NBPLoad, because the AppleTalk Manager calls it when necessary.
  8490.  
  8491. Result codes    noErr    No error
  8492.  
  8493. FUNCTION NBPUnload :  OSErr; [Not in ROM]
  8494.  
  8495. On a Macintosh 128K, NBPUnload makes the NBP code purgeable; the space isn’t actually
  8496. released by the Memory Manager until necessary. On a Macintosh 512K or Macintosh XL,
  8497. NBPUnload has no effect.
  8498.  
  8499. Result codes    noErr    No error
  8500.  
  8501. »Example
  8502.  
  8503. This example of NBP registers our node as a print spooler, searches for any print
  8504. spoolers registered on the network, and then extracts the information for the first
  8505. one found.
  8506.  
  8507. CONST
  8508.   mySocket = 20;
  8509.  
  8510. VAR
  8511.   myABRecord: ABRecHandle;
  8512.   myEntity: EntityName;
  8513.   entityAddr: AddrBlock;
  8514.   nbpNamePtr: Ptr;
  8515.   myBuffer: PACKED ARRAY [0..999] OF CHAR;
  8516.   errCode: INTEGER;
  8517.   async: BOOLEAN;
  8518.  
  8519. BEGIN
  8520.   errCode := MPPOpen;
  8521.   IF errCode <> noErr THEN
  8522.     WRITELN('Error in opening AppleTalk')
  8523.     {Maybe serial port B isn't available for use by AppleTalk}
  8524.   ELSE
  8525.     BEGIN
  8526.       {Call Memory Manager to allocate ABusRecord}
  8527.       myABRecord := ABRecHandle(NewHandle(nbpSize));
  8528.       {Set up our entity name to register}
  8529.       WITH myEntity DO
  8530.         BEGIN
  8531.           objStr := 'Gene Station'; {we are called 'Gene Station' }
  8532.           typeStr := 'PrintSpooler'; { and are of type 'PrintSpooler'}
  8533.           zoneStr := '*';
  8534.           {Allocate data space for the entity name (used by NBP)}
  8535.           nbpNamePtr := NewPtr(LENGTH(objStr) + LENGTH(typeStr) +
  8536.                                LENGTH(zoneStr) + 12);
  8537.         END;
  8538.       {Set up the ABusRecord for the NBPRegister call}
  8539.       WITH myABRecord^^ DO
  8540.         BEGIN
  8541.           nbpEntityPtr := @myEntity;
  8542.           nbpBufPtr := nbpNamePtr; {buffer used by NBP internally}
  8543.           nbpBufSize := nbpNameBufSize;
  8544.           nbpAddress.aSocket := mySocket; {socket to register us on}
  8545.           nbpRetransmitInfo.retransInterval := 8; {retransmit every 64 }
  8546.           nbpRetransmitInfo.retransCount := 3; { ticks and try 3 times}
  8547.         END;
  8548.       async := FALSE;
  8549.       errCode := NBPRegister(myABRecord, async);
  8550.       IF errCode <> noErr THEN
  8551.         WRITELN('Error occurred in the NBPRegister call')
  8552.         {Maybe the name is already registered somewhere else on the }
  8553.         { network.}
  8554.       ELSE
  8555.         BEGIN
  8556.           {Now that we've registered our name, find others of type }
  8557.           { 'PrintSpooler'.}
  8558.           WITH myEntity DO
  8559.             BEGIN
  8560.               objStr := '='; {any one of type }
  8561.               typeStr := 'PrintSpooler'; { “PrintSpooler” }
  8562.               zoneStr := '*'; { in our zone}
  8563.             END;
  8564.           WITH myABRecord^^ DO
  8565.             BEGIN
  8566.               nbpEntityPtr := @myEntity;
  8567.               nbpBufPtr := @myBuffer; {buffer to place responses in}
  8568.               nbpBufSize := SIZEOF(myBuffer);
  8569.              {The field nbpDataField, before the NBPLookup call, represents an }
  8570.               { approximate number of responses. After the call, nbpDataField }
  8571.               { contains the actual number of responses received.}
  8572.               nbpDataField := 100; {we want about 100 responses back}
  8573.             END;
  8574.           errCode := NBPLookup(myABRecord, async); {make sync call}
  8575.           IF errCode <> noErr THEN
  8576.             WRITELN('An error occurred in the NBPLookup')
  8577.             {Did the buffer overflow?}
  8578.           ELSE
  8579.             BEGIN
  8580.               {Get the first reply}
  8581.               errCode := NBPExtract(@mybuffer, myABRecord^^.nbpDataField, 1,
  8582.                                     myEntity, entityAddr);
  8583.            {The socket address and name of the entity are returned here. If we }
  8584.              { want all of them, we'll have to loop for each one in the buffer.}
  8585.               IF errCode <> noErr THEN WRITELN('Error in NBPExtract');
  8586.               {Maybe the one we wanted wasn't in the buffer}
  8587.             END;
  8588.         END;
  8589.     END;
  8590. END.
  8591.  
  8592. _______________________________________________________________________________
  8593.  
  8594. »Miscellaneous Routines
  8595.  
  8596. FUNCTION GetNodeAddress (VAR myNode,myNet:  INTEGER) :  OSErr; [Not in ROM]
  8597.  
  8598. GetNodeAddress returns the current node ID and network number of the caller. If the
  8599. .MPP driver isn’t installed, it returns noMPPErr. If myNet contains 0, this means
  8600. that a bridge hasn’t yet been found.
  8601.  
  8602. Result codes    noErr       No error
  8603.                 noMPPErr    MPP driver not installed
  8604.  
  8605. FUNCTION IsMPPOpen :  BOOLEAN; [Not in ROM]
  8606.  
  8607. IsMPPOpen returns TRUE if the .MPP driver is loaded and running.
  8608.  
  8609. FUNCTION IsATPOpen :  BOOLEAN; [Not in ROM]
  8610.  
  8611. IsATPOpen returns TRUE if the .ATP driver is loaded and running.
  8612.  
  8613. _______________________________________________________________________________
  8614.  
  8615.  
  8616. æKY New…AppleTalk…Manager…Pascal…Interface
  8617. æC »NEW APPLETALK MANAGER PASCAL INTERFACE                   AppleTalkManager
  8618. _______________________________________________________________________________
  8619.  
  8620. In addition to the interface documented in the previous section, a new parameter
  8621. block–style interface to the AppleTalk Manager is now available for Pascal programmers.
  8622. This new interface, referred to as the preferred interface, is available in addition
  8623. to the Pascal interface described in the previous section, which is referred to as
  8624. the alternate interface.  All AppleTalk Manager calls, old and new, are supported by
  8625. the preferred interface.
  8626.  
  8627. The alternate interface has not been extended to support the new AppleTalk Manager
  8628. calls.  However, the alternate interface provides the only implementation of LAPRead
  8629. and DDPRead. These are higher-level calls not directly supported through the assembly-language
  8630. interface.  Developers will wish to use the alternate interface for these calls, and
  8631. also for compatibility with previous applications.  In all other cases, it is recommended
  8632. that the new preferred interface be used.
  8633.  
  8634. _______________________________________________________________________________
  8635.  
  8636. »Using Pascal
  8637.  
  8638. All AppleTalk Manager calls in the  preferred interface are essentially equivalent to
  8639. the corresponding assembly-language calls.  Their form is
  8640.  
  8641. FUNCTION MPPCall (pbPtr: Ptr; asyncFlag: BOOLEAN) : OSErr;
  8642.  
  8643. where pbPtr points to a device manager parameter block, and asyncFlag is TRUE if the
  8644. call is to be executed asynchronously.  Three parameter block types are provided by
  8645. the preferred interface (MPP, ATP, and XPP).  The MPP parameter block is shown below.
  8646.  The ATP parameter block is shown in the following section, and the XPP parameter
  8647. block is shown in the “Calling the .XPP Driver” section of this document. The field
  8648. names in these parameter blocks are the same as the parameter block offset names
  8649. defined in the assembly-language section (except as documented below).  The caller
  8650. fills in the parameter block with the fields as specified in that section and issues
  8651. the appropriate call.  The interface issues the actual device manager control call.
  8652.  
  8653. On asynchronous calls, the caller may pass a completion routine pointer in the parameter
  8654. block, at offset ioCompletion.  This routine will be executed upon completion of the
  8655. call.  It is executed at interrupt level and must not make any memory manager calls. 
  8656. If it uses application globals, it must ensure that register A5 is set up correctly;
  8657. for details see SetupA5 and RestoreA5 in the Operating System Utilities chapter.  If
  8658. no completion routine is desired, ioCompletion should be set to NIL.
  8659.  
  8660. Asynchronous calls return control to the caller with result code of noErr as soon as
  8661. they are queued to the driver.  This isn’t an indication of successful completion. 
  8662. To determine when the call is actually completed, if you don’t want to use a completion
  8663. routine, you can poll the ioResult field; this field is set to 1 when the call is
  8664. made, and receives the actual result code upon completion.
  8665.  
  8666. Refer to the appropriate sections of this chapter for the parameter blocks used by
  8667. each MPP and ATP call.  As different MPP and ATP calls take different arguments in
  8668. their parameter block, two Pascal variant records have been defined to account for
  8669. all the different cases.  These parameter blocks are shown in the sections that
  8670. follow.  The first four fields (which are the same for all calls) are automatically
  8671. filled in by the device manager.  The csCode and ioRefnum fields are automatically
  8672. filled in by the interface, depending on which call is being made, except in XPP
  8673. where the caller must fill in the ioRefnum.  The ioVRefnum field is unused.
  8674.  
  8675. There are two fields that at the assembly-language level have more than one name. 
  8676. These two fields have been given only one name in the preferred interface.  These are
  8677. entityPtr and ntqelPtr, which are both referred to as entityPtr, and atpSocket and
  8678. currBitmap, which are both referred to as atpSocket. These are the only exceptions to
  8679. the naming convention.
  8680.  
  8681. »MPP Parameter Block
  8682.  
  8683. MPPParamBlock = PACKED RECORD
  8684.        qLink:          QElemPtr;     {next queue entry}
  8685.        qType:          INTEGER;      {queue type}
  8686.        ioTrap:         INTEGER;      {routine trap}
  8687.        ioCmdAddr:      Ptr;          {routine address}
  8688.        ioCompletion:   ProcPtr;      {completion routine}
  8689.        ioResult:       OSErr;        {result code}
  8690.        ioNamePtr:      StringPtr;    {command result (ATP user bytes) [long]}
  8691.        ioVRefNum:      INTEGER;      {volume reference or drive number}
  8692.        ioRefNum:       INTEGER;      {driver reference number}
  8693.        csCode:         INTEGER;      {call command code AUTOMATICALLY SET}
  8694.  
  8695.        CASE MPPParmType OF
  8696.        LAPWriteParm:
  8697.                     (filler0:INTEGER;
  8698.                     wdsPointer:Ptr);    {->Write Data Structure}
  8699.        AttachPHParm,DetachPHParm:
  8700.                     (protType:Byte;     {ALAP Protocol Type}
  8701.                     filler1:Byte;
  8702.                     handler:Ptr);       {->protocol handler routine}
  8703.        OpenSktParm,CloseSktParm,WriteDDPParm:
  8704.                     (socket:Byte;       {socket number}
  8705.                     checksumFlag:Byte;  {checksum flag}
  8706.                     listener:Ptr);      {->socket listener routine}
  8707.        RegisterNameParm,LookupNameParm,ConfirmNameParm,RemoveNameParm:
  8708.                     (interval:Byte;     {retry interval}
  8709.                     count:Byte;         {retry count}
  8710.                     entityPtr:Ptr;      {->names table element or }
  8711.                                         { ->entity name}
  8712.                     CASE MPPParmType OF
  8713.                     RegisterNameParm:
  8714.                              (verifyFlag:Byte;     {set if verify needed}
  8715.                               filler3:Byte);
  8716.                     LookupNameParm:
  8717.                                     (retBuffPtr:Ptr;       {->return buffer}
  8718.                                     retBuffSize:INTEGER;   {return buffer size}
  8719.                                     maxToGet:INTEGER;      {matches to get}
  8720.                                     numGotten:INTEGER);    {matched gotten}
  8721.                     ConfirmNameParm:
  8722.                                     (confirmAddr:AddrBlock; {->entity}
  8723.                                     newSocket:Byte;         {socket number}
  8724.                                     filler4:Byte));
  8725.  
  8726.        SetSelfSendParm:
  8727.                     (newSelfFlag:Byte;  {self-send toggle flag}
  8728.                     oldSelfFlag:Byte);  {previous self-send state}
  8729.        KillNBPParm:
  8730.                     (nKillQEl:Ptr);     {ptr to Q element to cancel}
  8731.      END;
  8732.  
  8733. »ATP Parameter Block
  8734.  
  8735. ATPParamBlock = PACKED RECORD
  8736.          qLink:            QElemPtr;    {next queue entry}
  8737.          qType:            INTEGER;     {queue type}
  8738.          ioTrap:           INTEGER;     {routine trap}
  8739.          ioCmdAddr:        Ptr;         {routine address}
  8740.          ioCompletion:     ProcPtr;     {completion routine}
  8741.          ioResult:         OSErr;       {result code}
  8742.          userData:         LONGINT;     {ATP user bytes [long]}
  8743.          reqTID:           INTEGER;     {request transaction ID}
  8744.          ioRefNum:         INTEGER;     {driver reference number
  8745.          csCode:           INTEGER;     {Call command code }
  8746.                                         { AUTOMATICALLY SET}
  8747.          atpSocket:        Byte;        {currBitMap or socket number}
  8748.          atpFlags:         Byte;        {control information}
  8749.          addrBlock:        AddrBlock;   {source/dest. socket address}
  8750.          reqLength:        INTEGER;     {request/response length}
  8751.          reqPointer:       Ptr;         {-> request/response data}
  8752.          bdsPointer:       Ptr;         {-> response BDS}
  8753.          CASE MPPParmType OF
  8754.                 SendRequestParm,NSendRequestParm:
  8755.                     (numOfBuffs:Byte;   {numOfBuffs}
  8756.                     timeOutVal:Byte;    {timeout interval}
  8757.                     numOfResps:Byte;    {number responses actually received}
  8758.                     retryCount:Byte;    {number of retries}
  8759.                     intBuff:INTEGER);   {used internally for NSendRequest}
  8760.                 SendResponseParm:
  8761.                     (filler0:Byte;      {number of responses being sent}
  8762.                     bdsSize:Byte;       {number of BDS elements}
  8763.                     transID:INTEGER);   {transaction ID}
  8764.                 GetRequestParm:
  8765.                     (bitMap:Byte;       {bit map}
  8766.                     filler1:Byte);
  8767.                 AddResponseParm:
  8768.                     (rspNum:Byte;       {sequence number}
  8769.                     filler2:Byte);
  8770.                 KillSendReqParm,KillGetReqParm:
  8771.                     (aKillQEl:Ptr);     {ptr to Q element to cancel}
  8772.          END;
  8773.  
  8774. The following table is a complete list of all the parameter block calls provided by
  8775. the preferred interface.
  8776.  
  8777. AppleTalk
  8778. Manager
  8779. Routine       Preferred Interface Call
  8780.  
  8781. AttachPH      Function PAttachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  8782. DetachPH      Function PDetachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  8783. WriteLAP      Function PWriteLAP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  8784. OpenSkt       Function POpenSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  8785. CloseSkt      Function PCloseSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  8786. WriteDDP      Function PWriteDDP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  8787. RegisterName  Function PRegisterName (thePBptr: MPPPBPtr;
  8788.                                       async: BOOLEAN) : OSErr;
  8789. LookupName    Function PLookupName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  8790. ConfirmName   Function PConfirmName (thePBptr: MPPPBPtr;
  8791.                                      async: BOOLEAN) : OSErr;
  8792. RemoveName    Function PRemoveName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  8793. OpenATPSkt    Function POpenATPSkt (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  8794. CloseATPSkt   Function PCloseATPSkt (thePBptr: ATPPBPtr;
  8795.                                      async: BOOLEAN) : OSErr;
  8796. SendRequest   Function PSendRequest (thePBptr: ATPPBPtr;
  8797.                                      async: BOOLEAN) : OSErr;
  8798. GetRequest    Function PGetRequest (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  8799. SendResponse  Function PSendResponse (thePBptr: ATPPBPtr;
  8800.                                       async: BOOLEAN) : OSErr;
  8801. AddResponse   Function PAddResponse(thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  8802. ReltCB        Function PRelTCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  8803. RelRspCB      Function PRelRspCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  8804. SetSelfSend   Function PSetSelfSend (thePBptr: MPPPBPtr;
  8805.                                      async: BOOLEAN) : OSErr;
  8806. NSendRequest  Function PNSendRequest (thePBptr: ATPPBPtr;
  8807.                                       async: BOOLEAN) : OSErr;
  8808. KillSendReq   Function PKillSendReq (thePBptr: ATPPBPtr;
  8809.                                      async: BOOLEAN) : OSErr;
  8810. KillGetReq    Function PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  8811. KillNBP       Function PKillNBP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  8812.  
  8813. _______________________________________________________________________________
  8814.  
  8815. »Building Data Structures
  8816.  
  8817. Because it is difficult for Pascal to deal with certain assembly-language structures,
  8818. the preferred interface provides a number of routines for building these structures. 
  8819. These routines are summarized below.
  8820.  
  8821. PROCEDURE BuildLAPwds (wdsPtr,dataPtr: Ptr;
  8822.                        destHost,protoType,frameLen: INTEGER);
  8823.  
  8824. This routine builds a single-frame write data structure LAP WDS for use with the
  8825. PWriteLAP call.  Given a buffer of length frameLen pointed to by dataPtr, it fills in
  8826. the WDS pointed to by wdsPtr and sets the destination node and protocol type as
  8827. indicated by destHost and protoType, respectively.  The WDS indicated must contain at
  8828. least two elements.
  8829.  
  8830. PROCEDURE BuildDDPwds  (wdsPtr,headerPtr,dataPtr: Ptr; destAddress: AddrBlock;
  8831.                         DDPType : INTEGER; dataLen: INTEGER);
  8832.  
  8833. This routine builds a single-frame write data structure  DDP WDS, for use with the
  8834. PWriteDDP call.  Given a header buffer of at least 17 bytes pointed to by headerPtr
  8835. and a data buffer of length dataLen pointed to by dataPtr, it fills in the WDS pointed
  8836. to by wdsPtr, and sets the destination address and protocol type as indicated by
  8837. destaddress and DDPtype, respectively.  The WDS indicated must contain at least 3
  8838. elements.
  8839.  
  8840. PROCEDURE NBPSetEntity (buffer: Ptr; nbpObject,nbpType,nbpZone: Str32);
  8841.  
  8842. This routine builds an NBP entity structure, for use with the PLookupNBP and PConfirmName
  8843. calls.  Given a buffer of at least the size of the EntityName data structure (99
  8844. bytes) pointed to by buffer, this routine sets the indicated object, type, and zone
  8845. in that buffer.
  8846.  
  8847. PROCEDURE NBPSetNTE (ntePtr: Ptr; nbpObject,nbpType,nbpZone: Str32;
  8848.                      Socket: INTEGER);
  8849.  
  8850. This routine builds an NBP names table entry, for use with the PRegisterName call. 
  8851. Given a names table entry of at least the size of the EntityName data structure plus
  8852. nine bytes (108 bytes) pointed to by ntePtr, this routine sets the indicated object,
  8853. type, zone, and socket in that names table entry.
  8854.  
  8855. FUNCTION NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne: INTEGER; VAR abEntity:
  8856. EntityName; VAR address: AddrBlock) : OSErr;
  8857.  
  8858. This routine is provided in the alternate interface, but can be used as provided for
  8859. extracting NBP entity names from a look-up response buffer.
  8860.  
  8861. FUNCTION GetBridgeAddress: INTEGER;
  8862.  
  8863. This routine returns the current address of a bridge in the low byte, or zero if
  8864. there is none.
  8865.  
  8866. FUNCTION BuildBDS (buffPtr,bdsPtr: Ptr; buffSize: INTEGER) : INTEGER;
  8867.  
  8868. This routine builds a BDS, for use with the ATP calls.  Given a data buffer of length
  8869. buffSize pointed to by buffPtr, it fills in the BDS pointed to by bdsPtr.  The buffer
  8870. will be broken up into pieces of maximum size (578 bytes).  The user bytes in the BDS
  8871. are not modified by this routine.  This routine is provided only as a convenience;
  8872. generally the caller will be able to build the BDS completely from Pascal without
  8873. it.
  8874.  
  8875. _______________________________________________________________________________
  8876.  
  8877.  
  8878. æKY Picking…a…Node…Address…in…the…Server…Range
  8879. æC »PICKING A NODE ADDRESS IN THE SERVER RANGE               AppleTalkManager
  8880. _______________________________________________________________________________
  8881.  
  8882. Normally upon opening, the node number picked by the AppleTalk manager will be in the
  8883. node number range ($01–$7F).  It is possible to indicate that a node number in the
  8884. server range ($80–$FE) is desired.  Picking a number in the server range is a more
  8885. time-consuming but more thorough process, and it’s required for server nodes because
  8886. it greatly decreases the possibility of a node number conflict.
  8887.  
  8888. To open AppleTalk with a server node number, an extended open call is used.  An
  8889. extended open call is indicated by having the immediate bit set in the Open trap
  8890. itself.  In the extended open call, the high bit (bit 31) of the extension longword
  8891. field (ioMix) indicates whether a server or workstation node number should be picked.
  8892.  Set this bit to 1 to request a server node number.  The rest of this field should be
  8893. zero, as should all other unused fields in the queue element.   A server node number
  8894. can only be requested on the first Open call to the .MPP driver.
  8895.  
  8896. _______________________________________________________________________________
  8897.  
  8898.  
  8899. æKY Sending…Packets…to…One’s…Own…Node
  8900. æC »SENDING PACKETS TO ONE’S OWN NODE                        AppleTalkManager
  8901. _______________________________________________________________________________
  8902.  
  8903. Upon opening, the ability to send a packet to one’s own node (intranode delivery) is
  8904. disabled.  This feature of the AppleTalk Manager can be manipulated through the
  8905. SetSelfSend function.  Once enabled, it is possible, at all levels, to send packets
  8906. to entities within one’s own node.  An example of where this might be desirable is an
  8907. application sending data to a print spooler that is actually running in the background
  8908. on the same node.
  8909.  
  8910. Enabling (or disabling) this feature affects the entire node and should be performed
  8911. with care.  For instance, a desk accessory may not expect to receive names from
  8912. within its own node as a response to an NBP look-up;  enabling this feature from an
  8913. application could break the desk accessory.  All future programs should be written
  8914. with this feature in mind.
  8915.  
  8916. FUNCTION PSetSelfSend (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  8917.  
  8918. Parameter Block
  8919.   -->    26    csCode         word    Always PSetSelfSend
  8920.   -->    28    newSelfFlag    byte    New SelfSend flag
  8921.   <--    29    oldSelfFlag    byte    Old SelfSend flag
  8922.  
  8923. PSetSelfSend enables or disables the intranode delivery feature of the AppleTalk
  8924. Manager.  If newSelfFlag is nonzero, the feature will be enabled; otherwise it will
  8925. be disabled.  The previous value of the flag will be returned in oldSelfFlag.
  8926.  
  8927. Result Codes    noErr        No error
  8928.  
  8929. _______________________________________________________________________________
  8930.  
  8931.  
  8932. æKY ATP…Driver…Changes
  8933. æC »ATP DRIVER CHANGES                                       AppleTalkManager
  8934. _______________________________________________________________________________
  8935.  
  8936. Changes to the ATP driver include the ability to send an ATP request through a specific
  8937. socket rather than having ATP open a new socket, a new call to abort outstanding
  8938. SendRequest calls, and a new call to abort specific outstanding GetRequest calls.
  8939.  
  8940. _______________________________________________________________________________
  8941.  
  8942. »Sending an ATP Request Through a Specified Socket
  8943.  
  8944. ATP requests can now be sent through client-specified sockets.  ATP previously would
  8945. open a dynamic socket, send the request through it, and close the socket when the
  8946. request was completed.  The client can now choose to send a request through an already-opened
  8947. socket; this also allows more than one request to be sent per socket.   A new call,
  8948. PNSendRequest, has been added for this purpose.  The function of the old SendRequest
  8949. call itself remains unchanged.
  8950.  
  8951. FUNCTION PNSendRequest (thePBptr: ATPBPtr; async: BOOLEAN) : OSErr;
  8952.  
  8953. Parameter block
  8954.   -->    18    userData     longword  User bytes
  8955.   <--    22    reqTID       word      Transaction ID used in request
  8956.   -->    26    csCode       word      Always sendRequest
  8957.   <->    28    atpSocket    byte      Socket to send request on
  8958.                                        or current bitmap
  8959.   <->    29    atpFlags     byte      Control information
  8960.   -->    30    addrBlock    longword  Destination socket address
  8961.   -->    34    reqLength    word      Request size in bytes
  8962.   -->    36    reqPointer   pointer   Pointer to request data
  8963.   -->    40    bdsPointer   pointer   Pointer to response BDS
  8964.   -->    44    numOfBuffs   byte      Number of responses expected
  8965.   -->    45    timeOutVal   byte      Timeout interval
  8966.   <--    46    numOf Resps  byte      Number of responses received
  8967.   <->    47    retryCount   byte      Number of retries
  8968.   <--    48    intBuff      word      Used internally
  8969.  
  8970. The PNSendRequest call is functionally equivalent to the SendRequest call, however
  8971. PNSendRequest allows you to specify, in the atpSocket field, the socket through which
  8972. the request is to be sent.  This socket must have been previously opened through an
  8973. OpenATPSkt request (otherwise a badATPSkt error will be returned).  Note that PNSendRequest
  8974. requires two additional bytes of memory at the end of the parameter block, immediately
  8975. following the retryCount.  These bytes are for the internal use of the AppleTalk
  8976. Manager and should not be modified while the PNSendRequest call is active.
  8977.  
  8978. There is a machine-dependent limit as to the number of concurrent PNSendRequests that
  8979. can be active on a given socket.  If this limit is exceeded, the error tooManyReqs is
  8980. returned.
  8981.  
  8982. One additional difference between SendRequest and PNSendRequest is that a PNSendRequest
  8983. can only be aborted by a PKillSendReq call (see below), whereas a SendRequest can be
  8984. aborted by either a RelTCB or KillSendReq call.
  8985.  
  8986. Result Codes    noErr          No error
  8987.                 reqFailed      Retry count exceeded
  8988.                 tooManyReqs    Too many concurrent requests
  8989.                 noDataArea     Too many outstanding ATP calls
  8990.                 reqAborted     Request cancelled by user
  8991.  
  8992. _______________________________________________________________________________
  8993.  
  8994. »Aborting ATP SendRequests
  8995.  
  8996. The  RelTCB call is still supported, but only for aborting SendRequests.  To abort
  8997. PNSendRequests, a new call, PKillSendReq, has been added.  This call will abort both
  8998. SendRequests and PNSendRequests.  PKillSendReq’s only argument is the queue element
  8999. pointer of the request to be aborted.  The queue element pointer is passed at the
  9000. offset of the PKillSendReq queue element specified by aKillQE1.
  9001.  
  9002. FUNCTION PKillSendReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  9003.  
  9004. Parameter block
  9005.   -->    26    csCode    word     Always PKillSendReq
  9006.   -->    44    aKillQEl  pointer  Pointer to queue element
  9007.  
  9008. PKillSendReq is functionally equivalent to RelTCB, except that it takes different
  9009. arguments and will abort both SendRequests and PNSendRequests.  To abort one of these
  9010. calls, place a pointer to the queue element of the call to abort in aKillQEl and
  9011. issue the PKillSendReq call.
  9012.  
  9013. Result Codes    noErr          No error
  9014.                 cbNotFound     aKillQEl does not point to a SendReq
  9015.                                or NSendReq queue element
  9016.  
  9017. _______________________________________________________________________________
  9018.  
  9019. »Aborting ATP GetRequests
  9020.  
  9021. ATP GetRequests can now be aborted through the PKillGetReq call.  This call looks and
  9022. works just like the PKillSendReq call, and is used to abort a specific GetRequest
  9023. call.  Previously it was necessary to close the socket  to abort all GetRequest calls
  9024. on the socket.
  9025.  
  9026. FUNCTION PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  9027.  
  9028. Parameter block
  9029.   -->    26    csCode    word     Always PKillGetReq
  9030.   -->    44    aKillQEl  pointer  Pointer to queue element
  9031.  
  9032. PKillGetReq will abort a specific outstanding GetRequest call (as opposed to closing
  9033. the socket, which aborts all outstanding GetRequests on that socket).  The call will
  9034. be completed with a reqAborted error.  To abort a GetRequest, place a pointer to the
  9035. queue element of the call to abort in aKillQEl and issue the PKillGetReq call.
  9036.  
  9037. Result Codes    noErr         No error
  9038.                 cbNotFound    aKillQEl does not point to a GetReq
  9039.                               queue element
  9040.  
  9041. _______________________________________________________________________________
  9042.  
  9043.  
  9044. æKY Name…Binding…Protocol…Changes
  9045. æC »NAME BINDING PROTOCOL CHANGES                            AppleTalkManager
  9046. _______________________________________________________________________________
  9047.  
  9048. Changes to the Name Binding Protocol include supporting multiple concurrent requests
  9049. and a means for aborting an active request.
  9050.  
  9051. »Multiple Concurrent NBP Requests
  9052.  
  9053. NBP now supports multiple concurrent active requests.  Specifically, a number of
  9054. LookupNames, RegisterNames and ConfirmNames can all be active concurrently.  The
  9055. maximum number of  concurrent requests is machine dependent; if it is exceeded the
  9056. error tooManyReqs will be returned.  Active requests can be aborted by the PKillNBP
  9057. call.
  9058.  
  9059. »KillNBP function
  9060.  
  9061. FUNCTION PKillNBP (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  9062.  
  9063. •••Refer to Technical Note #199:•••
  9064.  
  9065. Parameter block
  9066.   -->    26    csCode    word     Always PKillNBP
  9067.   -->    28    aKillQEl  pointer  Pointer to queue element
  9068.  
  9069. PKillNBP is used to abort an outstanding LookupName, RegisterName or ConfirmName
  9070. request.  To abort one of these calls, place a pointer to the queue element of the
  9071. call to abort in a KillQEl and issue the PKillNBP call.  The call will be completed
  9072. with a ReqAborted error.
  9073.  
  9074. Result Codes    noErr          No error
  9075.                 cbNotFound     aKillQEl does not point to a valid
  9076.                                NBP queue element
  9077.  
  9078. _______________________________________________________________________________
  9079.  
  9080.  
  9081. æKY Variable…Resources
  9082. æC »VARIABLE RESOURCES                                       AppleTalkManager
  9083. _______________________________________________________________________________
  9084.  
  9085. The table below lists machine-dependent resources for the different Macintosh system
  9086. configurations.  The RAM-based resources are available through the AppleShare Server.
  9087.  
  9088. Resource    Macintosh Plus    RAM-Based    Macintosh SE    Macintosh II
  9089.  
  9090. Protocol
  9091. Handlers           4             8              8               8
  9092.  
  9093. Statically
  9094. Assigned
  9095. Sockets           14*           12             12              14
  9096.  
  9097. Concurrent
  9098. ATP SendRequests   6            12             12              12
  9099.  
  9100. ATP Sockets        6            32             32             126
  9101.  
  9102. Concurrent
  9103. ATP Responses      8            16             16              32
  9104.  
  9105. Concurrent
  9106. NBP Requests       1             6              6              10
  9107.  
  9108. Concurrent
  9109. ASP Sessions      N/A            5             10              20
  9110.  
  9111. Concurrent
  9112. ATP NSendRequests
  9113. Per Socket **     N/A            9             14              62
  9114.  
  9115. * Includes dynamic sockets
  9116. **  Determined dynamically at runtime based on CPU speed.
  9117. N/A : Not Applicable
  9118.  
  9119. _______________________________________________________________________________
  9120.  
  9121.  
  9122. æKY Calling…the…AppleTalk…Manager…from…Assembly…Language
  9123. æC »CALLING THE APPLETALK MANAGER FROM ASSEMBLY LANGUAGE      AppleTalkManager
  9124. _______________________________________________________________________________
  9125.  
  9126. This section discusses how to use the AppleTalk Manager from assembly language.
  9127. Equivalent Pascal information is given in the preceding section.
  9128.  
  9129. All routines make Device Manager Control calls. The description of each routine
  9130. includes a list of the fields needed. Some of these fields are part of the parameter
  9131. block described in the Device Manager chapter; additional fields are provided for the
  9132. AppleTalk Manager.
  9133.  
  9134. The number next to each field name indicates the byte offset of the field from the
  9135. start of the parameter block pointed to by A0. An arrow next to each parameter name
  9136. indicates whether it’s an input, output, or input/output parameter:
  9137.  
  9138. Arrow    Meaning
  9139.   -->    Parameter is passed to the routine
  9140.   <--    Parameter is returned by the routine
  9141.   <->    Parameter is passed to and returned by the routine
  9142.  
  9143. All Device Manager Control calls return an integer result code of type OSErr in the
  9144. ioResult field. Each routine description lists all of the applicable result codes
  9145. generated by the AppleTalk Manager, along with a short description of what the result
  9146. code means. Lengthier explanations of all the result codes can be found in the summary
  9147. at the end of this chapter. Result codes from other parts of the Operating System may
  9148. also be returned. (See Appendix A for a list of all result codes.)
  9149.  
  9150. _______________________________________________________________________________
  9151.  
  9152. »Opening AppleTalk
  9153.  
  9154. •••Refer to Technical Note #224:•••
  9155.  
  9156. Two tests are made at system startup to determine whether the .MPP driver should be
  9157. opened at that time. If port B is already in use, or isn’t configured for AppleTalk,
  9158. .MPP isn’t opened until explicitly requested by an application; otherwise it’s opened
  9159. at system startup.
  9160.  
  9161. It’s the application’s responsibility to test the availability of port B before
  9162. opening AppleTalk. Assembly-language programmers can use the Pascal calls MPPOpen and
  9163. ATPLoad to open the .MPP and .ATP drivers.
  9164.  
  9165. The global variable SPConfig is used for configuring the serial ports; it’s copied
  9166. from a byte in parameter RAM (which is discussed in the Operating System Utilities
  9167. chapter). The low-order four bits of this variable contain the current configuration
  9168. of port B. The following use types are provided as global constants for testing or
  9169. setting the configuration of port B:
  9170.  
  9171.   useFree     .EQU    0    ;unconfigured
  9172.   useATalk    .EQU    1    ;configured for AppleTalk
  9173.   useAsync    .EQU    2    ;configured for the Serial Driver
  9174.  
  9175. The application shouldn’t attempt to open AppleTalk unless SPConfig is equal to
  9176. either useFree or useATalk.
  9177.  
  9178. A second test involves the global variable PortBUse; the low-order four bits of this
  9179. byte are used to monitor the current use of port B. If PortBUse is negative, the
  9180. program is free to open AppleTalk. If PortBUse is positive, the program should test
  9181. to see whether port B is already being used by AppleTalk; if it is, the low-order
  9182. four bits of PortBUse will be equal to the use type useATalk.
  9183.  
  9184. The .MPP driver sets PortBUse to the correct value (useATalk) when it’s opened and
  9185. resets it to $FF when it’s closed. Bits 4-6 of this byte are used for driver-specific
  9186. information; ATP uses bit 4 to indicate whether it’s currently opened:
  9187.  
  9188. atpLoadedBit    .EQU    4    ;set if ATP is opened
  9189.  
  9190. »Example
  9191.  
  9192. The following code illustrates the use of the SPConfig and PortBUse variables.
  9193.  
  9194.           MOVE      #-<atpUnitNum+1>,atpRefNum(A0)  ;save known ATP refNum in
  9195.                                                     ; case ATP not opened
  9196. OpenAbus  SUB       #ioQElSize,SP     ;allocate queue entry
  9197.           MOVE.L    SP,A0             ;A0 -> queue entry
  9198.           CLR.B     ioPermssn(A0)     ;make sure permission's clear
  9199.           MOVE.B    PortBUse,D1       ;is port B in use?
  9200.           BPL.S     @10               ;if so, make sure by AppleTalk
  9201.           MOVEQ     #portNotCf,D0     ;assume port not configured for AppleTalk
  9202.           MOVE.B    SPConfig,D1       ;get configuration data
  9203.           AND.B     #$0F,D1           ;mask it to low 4 bits
  9204.           SUBQ.B    #useATalk,D1      ;unconfigured or configured for AppleTalk
  9205.           BGT.S     @30               ;if not, return error
  9206.           LEA       mppName,A1        ;A1 = address of driver name
  9207.           MOVE.L    A1,ioFileName(A0) ;set in queue entry
  9208.           _Open                       ;open MPP
  9209.           BNE.S     @30               ;return error, if it can't load it
  9210.           BRA.S     @20               ;otherwise, go check ATP
  9211. @10       MOVEQ     #portInUse,D0     ;assume port in use error
  9212.           AND.B     #$0F,D1           ;clear all but use bits
  9213.           SUBQ.B    #useATalk,D1      ;is AppleTalk using it?
  9214.           BNE.S     @30               ;if not, then error
  9215. @20       MOVEQ     #0,D0             ;assume no error
  9216.           BTST      #atpLoadedBit,PortBUse    ;ATP already open?
  9217.           BNE.S     @30               ;just return if so
  9218.           LEA       atpName,A1        ;A1 = address of driver name
  9219.           MOVE.L    A1,ioFileName(A0) ;set in queue entry
  9220.           _Open                       ;open ATP
  9221. @30       ADD       #ioQElSize,SP     ;deallocate queue entry
  9222.           RTS                         ;and return
  9223. mppName   .BYTE     4                 ;length of .MPP driver name
  9224.           .ASCII    '.MPP'            ;name of .MPP driver
  9225. atpName   .BYTE     4                 ;length of .ATP driver name
  9226.           .ASCII    '.ATP'            ;name of .ATP driver
  9227.  
  9228. _______________________________________________________________________________
  9229.  
  9230. »AppleTalk Link Access Protocol
  9231.  
  9232. »Data Structures
  9233.  
  9234. An ALAP frame is composed of a three-byte header, up to 600 bytes of data, and a
  9235. two-byte frame check sequence (Figure 6). You can use the following global constants
  9236. to access the contents of an ALAP header:
  9237.  
  9238.   lapDstAdr  .EQU    0    ;destination node ID
  9239.   lapSrcAdr  .EQU    1    ;source node ID
  9240.   lapType    .EQU    2    ;ALAP protocol type
  9241.   lapHdSz    .EQU    3    ;ALAP header size
  9242.  
  9243. •••Refer to Figure 6.•••
  9244.  
  9245. Figure 6–ALAP Frame
  9246.  
  9247. Two of the protocol handlers in every node are used by DDP. These protocol handlers
  9248. service frames with ALAP protocol types equal to the following global constants:
  9249.  
  9250.   shortDDP   .EQU    1    ;short DDP header
  9251.   longDDP    .EQU    2    ;long DDP header
  9252.  
  9253. When you call ALAP to send a frame, you pass it information about the frame in a
  9254. write data structure, which has the format shown in Figure 7.
  9255.  
  9256. •••Refer to Figure 7.•••
  9257.  
  9258. Figure 7–Write Data Structure for ALAP
  9259.  
  9260. If you specify a destination node ID of 255, the frame will be broadcast to all
  9261. nodes. The byte that’s “used internally” is used by the AppleTalk Manager to store
  9262. the address of the node sending the frame.
  9263.  
  9264. »Using ALAP
  9265.  
  9266. Most programs will never need to call ALAP, because higher-level protocols will
  9267. automatically call ALAP as necessary. If you do want to send a frame directly via an
  9268. ALAP, call the WriteLAP function. There’s no ReadLAP function in assembly language;
  9269. if you want to read ALAP frames, you must call AttachPH to add your protocol handler
  9270. to the node’s protocol handler table. The ALAP module will examine every incoming
  9271. frame and call your protocol handler for each frame received with the correct ALAP
  9272. protocol. When your program no longer wants to receive frames with a particular ALAP
  9273. protocol type value, it can call DetachPH to remove the corresponding protocol handler
  9274. from the protocol handler table.
  9275.  
  9276. See the “Protocol Handlers and Socket Listeners” section for information on how to
  9277. write a protocol handler.
  9278.  
  9279. »ALAP Routines
  9280.  
  9281. WriteLAP function
  9282.  
  9283. Parameter block
  9284.   -->    26    csCode      word     ;always writeLAP
  9285.   -->    30    wdsPointer  pointer  ;write data structure
  9286.  
  9287. WriteLAP sends a frame to another node. The frame data and destination of the frame
  9288. are described by the write data structure pointed to by wdsPointer. The first two
  9289. data bytes of an ALAP frame sent to another computer using the AppleTalk Manager must
  9290. indicate the length of the frame in bytes. The ALAP protocol type byte must be in the
  9291. range 1 to 127.
  9292.  
  9293. Result codes    noErr            No error
  9294.                 excessCollsns    No CTS received after 32 RTS’s
  9295.                 ddpLengthErr     Packet length exceeds maximum
  9296.                 lapProtErr       Invalid ALAP protocol type
  9297.  
  9298. AttachPH function
  9299.  
  9300. Parameter block
  9301.   -->    26    csCode    word     ;always attachPH
  9302.   -->    28    protType  byte     ;ALAP protocol type
  9303.   -->    30    handler   pointer  ;protocol handler
  9304.  
  9305. AttachPH adds the protocol handler pointed to by handler to the node’s protocol
  9306. table. ProtType specifies what kind of frame the protocol handler can service. After
  9307. AttachPH is called, the protocol handler is called for each incoming frame whose ALAP
  9308. protocol type equals protType.
  9309.  
  9310. Result codes    noErr         No error
  9311.                 lapProtErr    Error attaching protocol type
  9312.  
  9313. DetachPH function
  9314.  
  9315. Parameter block
  9316.   -->    26    csCode    word  ;always detachPH
  9317.   -->    28    protType  byte  ;ALAP protocol type
  9318.  
  9319. DetachPH removes from the node’s protocol table the specified ALAP protocol type and
  9320. corresponding protocol handler.
  9321.  
  9322. Result codes    noErr         No error
  9323.                 lapProtErr    Error detaching protocol type
  9324.  
  9325. _______________________________________________________________________________
  9326.  
  9327. »Datagram Delivery Protocol
  9328.  
  9329. »Data Structures
  9330.  
  9331. A DDP datagram consists of a header followed by up to 586 bytes of actual data
  9332. (Figure 8). The headers can be of two different lengths; they’re identified by the
  9333. following ALAP protocol types:
  9334.  
  9335.   shortDDP   .EQU    1    ;short DDP header
  9336.   longDDP    .EQU    2    ;long DDP header
  9337.  
  9338. •••Refer to Figure 8.•••
  9339.  
  9340. Figure 8–DDP Datagram
  9341.  
  9342. Long DDP headers (13 bytes) are used for sending datagrams between two or more different
  9343. AppleTalk networks. You can use the following global constants to access the contents
  9344. of a long DDP header:
  9345.  
  9346.   ddpHopCnt    .EQU    0    ;count of bridges passed (4 bits)
  9347.   ddpLength    .EQU    0    ;datagram length (10 bits)
  9348.   ddpChecksum  .EQU    2    ;checksum
  9349.   ddpDstNet    .EQU    4    ;destination network number
  9350.   ddpSrcNet    .EQU    6    ;source network number
  9351.   ddpDstNode   .EQU    8    ;destination node ID
  9352.   ddpSrcNode   .EQU    9    ;source node ID
  9353.   ddpDstSkt    .EQU    10   ;destination socket number
  9354.   ddpSrcSkt    .EQU    11   ;source socket number
  9355.   ddpType      .EQU    12   ;DDP protocol type
  9356.  
  9357. The size of a DDP long header is given by the following constant:
  9358.  
  9359.   ddpHSzLong   .EQU    ddpType+1
  9360.  
  9361. The short headers (five bytes) are used for datagrams sent to sockets within the same
  9362. network as the source socket. You can use the following global constants to access
  9363. the contents of a short DDP header:
  9364.  
  9365.   ddpLength    .EQU    0               ;datagram length
  9366.   sDDPDstSkt   .EQU    ddpChecksum     ;destination socket number
  9367.   sDDPSrcSkt   .EQU    sDDPDstSkt+1    ;source socket number
  9368.   sDDPType     .EQU    sDDPSrcSkt+1    ;DDP protocol type
  9369.  
  9370. The size of a DDP short header is given by the following constant:
  9371.  
  9372.   ddpHSzShort  .EQU    sDDPType+1
  9373.  
  9374. The datagram length is a ten-bit field. You can use the following global constant as
  9375. a mask for these bits:
  9376.  
  9377.   ddpLenMask   .EQU    $03FF
  9378.  
  9379. The following constant indicates the maximum length of a DDP datagram:
  9380.  
  9381.   ddpMaxData   .EQU    586
  9382.  
  9383. When you call DDP to send a datagram, you pass it information about the datagram in a
  9384. write data structure with the format shown in Figure 9.
  9385.  
  9386. •••Refer to Figure 9.•••
  9387.  
  9388. Figure 9–Write Data Structure for DDP
  9389.  
  9390. The first seven bytes are used internally for the ALAP header and the DDP datagram
  9391. length and checksum. The other bytes used internally store the network number, node
  9392. ID, and socket number of the socket client sending the datagram.
  9393.  
  9394. Warning:  The first entry in a DDP write data structure must begin at
  9395.           an odd address.
  9396.  
  9397. If you specify a node ID of 255, the datagram will be broadcast to all nodes within
  9398. the destination network. A network number of 0 means the local network to which the
  9399. node is connected.
  9400.  
  9401. Warning:  DDP always destroys the high-order byte of the destination
  9402.           network number when it sends a datagram with a short header.
  9403.           Therefore, if you want to reuse the first entry of a DDP write
  9404.           data structure entry, you must restore the destination network number.
  9405.  
  9406. »Using DDP
  9407.  
  9408. Before it can use a socket, the program must call OpenSkt, which adds a socket and
  9409. its socket listener to the socket table. When a client is finished using a socket,
  9410. call CloseSkt, which removes the socket’s entry from the socket table. To send a
  9411. datagram via DDP, call WriteDDP. If you want to read DDP datagrams, you must write
  9412. your own socket listener. DDP will send every incoming datagram for that socket to
  9413. your socket listener.
  9414.  
  9415. See the “Protocol Handlers and Socket Listeners” section for information on how to
  9416. write a socket listener.
  9417.  
  9418. »DDP Routines
  9419.  
  9420. OpenSkt function
  9421.  
  9422. Parameter block
  9423.   -->    26    csCode    word     ;always openSkt
  9424.   <->    28    socket    byte     ;socket number
  9425.   -->    30    listener  pointer  ;socket listener
  9426.  
  9427. OpenSkt adds a socket and its socket listener to the socket table. If the socket
  9428. parameter is nonzero, it must be in the range 64 to 127, and it specifies the socket’s
  9429. number; if socket is 0, OpenSkt opens a socket with a socket number in the range 128
  9430. to 254, and returns it in the socket parameter. Listener contains a pointer to the
  9431. socket listener.
  9432.  
  9433. OpenSkt will return ddpSktErr if you pass the number of an already opened socket, if
  9434. you pass a socket number greater than 127, or if the socket table is full (the socket
  9435. table can hold a maximum of 12 sockets).
  9436.  
  9437. Result codes    noErr        No error
  9438.                 ddpSktErr    Socket error
  9439.  
  9440. CloseSkt function
  9441.  
  9442. Parameter block
  9443.   -->    26    csCode  word  ;always closeSkt
  9444.   -->    28    socket  byte  ;socket number
  9445.  
  9446. CloseSkt removes the entry of the specified socket from the socket table. If you pass
  9447. a socket number of 0, or if you attempt to close a socket that isn’t open, CloseSkt
  9448. will return ddpSktErr.
  9449.  
  9450. Result codes    noErr        No error
  9451.                 ddpSktErr    Socket error
  9452.  
  9453. WriteDDP function
  9454.  
  9455. Parameter block
  9456.   -->    26    csCode        word     ;always writeDDP
  9457.   -->    28    socket        byte     ;socket number
  9458.   -->    29    checksumFlag  byte     ;checksum flag
  9459.   -->    30    wdsPointer    pointer  ;write data structure
  9460.  
  9461. WriteDDP sends a datagram to another socket. WDSPointer points to a write data structure
  9462. containing the datagram and the address of the destination socket. If checksumFlag is
  9463. TRUE, WriteDDP will compute the checksum for all datagrams requiring long headers.
  9464.  
  9465. Result codes    noErr          No error
  9466.                 ddpLenErr      Datagram length too big
  9467.                 ddpSktErr      Socket error
  9468.                 noBridgeErr    No bridge found
  9469.  
  9470. _______________________________________________________________________________
  9471.  
  9472. »AppleTalk Transaction Protocol
  9473.  
  9474. »Data Structures
  9475.  
  9476. An ATP packet consists of an ALAP header, DDP header, and ATP header, followed by
  9477. actual data (Figure 10). You can use the following global constants to access the
  9478. contents of an ATP header:
  9479.  
  9480.   atpControl   .EQU    0    ;control information
  9481.   atpBitMap    .EQU    1    ;bit map
  9482.   atpRespNo    .EQU    1    ;sequence number
  9483.   atpTransID   .EQU    2    ;transaction ID
  9484.   atpUserData  .EQU    4    ;user bytes
  9485.  
  9486. The size of an ATP header is given by the following constant:
  9487.  
  9488.   atpHdSz      .EQU    8
  9489.  
  9490. •••Refer to Figure 10.•••
  9491.  
  9492. Figure 10–ATP Packet
  9493.  
  9494. ATP packets are identified by the following DDP protocol type:
  9495.  
  9496.   atp          .EQU    3
  9497.  
  9498. The control information contains a function code and various control bits. The function
  9499. code identifies either a TReq, TResp, or TRel packet with one of the following global
  9500. constants:
  9501.  
  9502.   atpReqCode   .EQU    $40    ;TReq packet
  9503.   atpRspCode   .EQU    $80    ;TResp packet
  9504.   atpRelCode   .EQU    $C0    ;TRel packet
  9505.  
  9506. The send-transmission-status, end-of-message, and exactly-once bits in the control
  9507. information are accessed via the following global constants:
  9508.  
  9509.   atpSTSBit    .EQU    3    ;send-transmission-status bit
  9510.   atpEOMBit    .EQU    4    ;end-of-message bit
  9511.   atpXOBit     .EQU    5    ;exactly-once bit
  9512.  
  9513. Many ATP calls require a field called atpFlags (Figure 11), which contains the above
  9514. three bits plus the following two bits:
  9515.  
  9516.   sendChk      .EQU    0    ;send-checksum bit
  9517.   tidValid     .EQU    1    ;transaction ID validity bit
  9518.  
  9519. •••Refer to Figure 11.•••
  9520.  
  9521. Figure 11–ATPFlags Field
  9522.  
  9523. The maximum number of response packets in an ATP transaction is given by the following
  9524. global constant:
  9525.  
  9526.   atpMaxNum    .EQU    8
  9527.  
  9528. When you call ATP to send responses, you pass the responses in a response BDS, which
  9529. is a list of up to eight elements, each of which contains the following:
  9530.  
  9531.   bdsBuffSz    .EQU    0    ;size of data to send
  9532.   bdsBuffAddr  .EQU    2    ;pointer to data
  9533.   bdsUserData  .EQU    8    ;user bytes
  9534.  
  9535. When you call ATP to receive responses, you pass it a response BDS with up to eight
  9536. elements, each in the following format:
  9537.  
  9538.   bdsBuffSz    .EQU    0    ;buffer size in bytes
  9539.   bdsBuffAddr  .EQU    2    ;pointer to buffer
  9540.   bdsDataSz    .EQU    6    ;number of bytes actually received
  9541.   bdsUserData  .EQU    8    ;user bytes
  9542.  
  9543. The size of a BDS element is given by the following constant:
  9544.  
  9545.   bdsEntrySz   .EQU    12
  9546.  
  9547. ATP clients are identified by internet addresses in the form shown in Figure 12.
  9548.  
  9549. •••Refer to Figure 12.•••
  9550.  
  9551. Figure 12–Internet Address
  9552.  
  9553. »Using ATP
  9554.  
  9555. Before you can use ATP on a Macintosh 128K, the .ATP driver must be read from the
  9556. system resource file via a Device Manager Open call. The name of the .ATP driver is
  9557. '.ATP' and its reference number is –11. When the .ATP driver is opened, it reads its
  9558. ATP code into the application heap and installs a task into the vertical retrace
  9559. queue.
  9560.  
  9561. Warning:  When another application starts up, the application heap is
  9562.           reinitialized; on a Macintosh 128K, this means that the ATP
  9563.           code is lost (and must be reloaded by the next application).
  9564.  
  9565. When you’re through using ATP on a Macintosh 128K, call the Device Manager Close
  9566. routine—the system will be returned to the state it was in before the
  9567. .ATP driver was opened.
  9568.  
  9569. On a Macintosh 512K or XL, the .ATP driver will have been loaded into the system heap
  9570. either at system startup or upon execution of a Device Manager Open call loading MPP.
  9571. You shouldn’t close the .ATP driver on a Macintosh 512K or XL; AppleTalk expects it
  9572. to remain open on these systems.
  9573.  
  9574. To send a request to another socket and get a response, call SendRequest. The call
  9575. terminates when either an entire response is received or a specified retry timeout
  9576. interval elapses. To open a socket for the purpose of responding to requests, call
  9577. OpenATPSkt. Then call GetRequest to receive a request; when a request is received,
  9578. the call is completed. After receiving and servicing a request, call SendResponse to
  9579. return response information. If you cannot or do not want to send the entire response
  9580. all at once, make a SendResponse call to send some of the response, and then call
  9581. AddResponse later to send the remainder of the response. To close a socket opened for
  9582. the purpose of sending responses, call CloseATPSkt.
  9583.  
  9584. During exactly-once transactions, SendResponse doesn’t terminate until the transaction
  9585. is completed via a TRel packet, or the retry count is exceeded.
  9586.  
  9587. Warning:  Don’t modify the parameter block passed to an ATP call until
  9588.           the call is completed.
  9589.  
  9590. »ATP Routines
  9591.  
  9592. OpenATPSkt function
  9593.  
  9594. Parameter block
  9595.   -->    26    csCode     word       ;always openATPSkt
  9596.   <->    28    atpSocket  byte       ;socket number
  9597.   -->    30    addrBlock  long word  ;socket request specification
  9598.  
  9599. OpenATPSkt opens a socket for the purpose of receiving requests. ATPSocket contains
  9600. the socket number of the socket to open. If it’s 0, a number is dynamically assigned
  9601. and returned in atpSocket. AddrBlock contains a specification of the socket addresses
  9602. from which requests will be accepted. A 0 in the network number, node ID, or socket
  9603. number field of addrBlock means that requests will be accepted from every network,
  9604. node, or socket, respectively.
  9605.  
  9606. Result codes    noErr          No error
  9607.                 tooManySkts    Too many responding sockets
  9608.                 noDataArea     Too many outstanding ATP calls
  9609.  
  9610. CloseATPSkt function
  9611.  
  9612. Parameter block
  9613.   -->    26    csCode     word    ;always closeATPSkt
  9614.   -->    28    atpSocket  byte    ;socket number
  9615.  
  9616. CloseATPSkt closes the socket whose number is specified by atpSocket, for the purpose
  9617. of receiving requests.
  9618.  
  9619. Result codes    noErr         No error
  9620.                 noDataArea    Too many outstanding ATP calls
  9621.  
  9622. SendRequest function
  9623.  
  9624. Parameter block
  9625.   -->    18    userData    long word  ;user bytes
  9626.   <--    22    reqTID      word       ;transaction ID used in request
  9627.   -->    26    csCode      word       ;always sendRequest
  9628.   <--    28    currBitMap  byte       ;bit map
  9629.   <->    29    atpFlags    byte       ;control information
  9630.   -->    30    addrBlock   long word  ;destination socket address
  9631.   -->    34    reqLength   word       ;request size in bytes
  9632.   -->    36    reqPointer  pointer    ;pointer to request data
  9633.   -->    40    bdsPointer  pointer    ;pointer to response BDS
  9634.   -->    44    numOfBuffs  byte       ;number of responses expected
  9635.   -->    45    timeOutVal  byte       ;timeout interval
  9636.   <--    46    numOfResps  byte       ;number of responses received
  9637.   <->    47    retryCount  byte       ;number of retries
  9638.  
  9639. SendRequest sends a request to another socket and waits for a response. UserData
  9640. contains the four user bytes. AddrBlock indicates the socket to which the request
  9641. should be sent. ReqLength and reqPointer contain the size and location of the request
  9642. to send. BDSPointer points to a response BDS where the responses are to be returned;
  9643. numOfBuffs indicates the number of responses requested. The number of responses
  9644. received is returned in numOfResps. If a nonzero value is returned in numOfResps, you
  9645. can examine currBitMap to determine which packets of the transaction were actually
  9646. received and to detect pieces for higher-level recovery, if desired.
  9647.  
  9648. TimeOutVal indicates the number of seconds that SendRequest should wait for a response
  9649. before resending the request. RetryCount indicates the maximum number of retries
  9650. SendRequest should attempt. The end-of-message flag of atpFlags will be set if the
  9651. EOM bit is set in the last packet received in a valid response sequence. The exactly-once
  9652. flag should be set if you want the request to be part of an exactly-once transaction.
  9653.  
  9654. To cancel a SendRequest call, you need the transaction ID; it’s returned in reqTID.
  9655. You can examine reqTID before the completion of the call, but its contents are valid
  9656. only after the tidValid bit of atpFlags has been set.
  9657.  
  9658. SendRequest completes when either an entire response is received or the retry count
  9659. is exceeded.
  9660.  
  9661. Note:  The value provided in retryCount will be modified during SendRequest
  9662.        if any retries are made. This field is used to monitor the number of
  9663.        retries; for each retry, it’s decremented by 1.
  9664.  
  9665. Result codes    noErr          No error
  9666.                 reqFailed      Retry count exceeded
  9667.                 tooManyReqs    Too many concurrent requests
  9668.                 noDataArea     Too many outstanding ATP calls
  9669.                 reqAborted     Request canceled by user
  9670.  
  9671. GetRequest function
  9672.  
  9673. Parameter block
  9674.   <--    18    userData    long word  ;user bytes
  9675.   -->    26    csCode      word       ;always getRequest
  9676.   -->    28    atpSocket   byte       ;socket number
  9677.   <--    29    atpFlags    byte       ;control information
  9678.   <--    30    addrBlock   long word  ;source of request
  9679.   <->    34    reqLength   word       ;request buffer size
  9680.   -->    36    reqPointer  pointer    ;pointer to request buffer
  9681.   <--    44    bitMap      byte       ;bit map
  9682.   <--    46    transID     word       ;transaction ID
  9683.  
  9684. GetRequest sets up the mechanism to receive a request sent by a SendRequest call.
  9685. UserData returns the four user bytes from the request. ATPSocket contains the socket
  9686. number of the socket that should listen for a request. The internet address of the
  9687. socket from which the request was sent is returned in addrBlock. ReqLength and reqPointer
  9688. indicate the size (in bytes) and location of a buffer to store the incoming request.
  9689. The actual size of the request is returned in reqLength. The transaction bit map and
  9690. transaction ID will be returned in bitMap and transID. The exactly-once flag in
  9691. atpFlags will be set if the request is part of an exactly-once transaction.
  9692.  
  9693. GetRequest completes when a request is received.
  9694.  
  9695. Result codes    noErr        No error
  9696.                 badATPSkt    Bad responding socket
  9697.  
  9698. SendResponse function
  9699.  
  9700. Parameter block
  9701.   <--    18    userData    long word  ;user bytes from TRel
  9702.   <--    22    reqTID      word       ;transaction ID used in request
  9703.   -->    26    csCode      word       ;always sendResponse
  9704.   -->    28    atpSocket   byte       ;socket number
  9705.   -->    29    atpFlags    byte       ;control information
  9706.   -->    30    addrBlock   long word  ;response destination
  9707.   -->    40    bdsPointer  pointer    ;pointer to response BDS
  9708.   -->    44    numOfBuffs  byte       ;number of response packets being sent
  9709.   -->    45    bdsSize     byte       ;BDS size in elements
  9710.   -->    46    transID     word       ;transaction ID
  9711.  
  9712. SendResponse sends a response to a socket. If the response was part of an exactly-once
  9713. transaction, userData will contain the user bytes from the TRel packet. ATPSocket
  9714. contains the socket number from which the response should be sent. The end-of-message
  9715. flag in atpFlags should be set if the response contains the final packet in a transaction
  9716. composed of a group of packets and the number of responses is less than requested.
  9717. AddrBlock indicates the address of the socket to which the response should be sent.
  9718. BDSPointer points to a response BDS containing room for the maximum number of responses
  9719. to be sent; bdsSize contains this maximum number. NumOfBuffs contains the number of
  9720. response packets to be sent in this call; you may wish to make AddResponse calls to
  9721. complete the response. TransID indicates the transaction ID of the associated request.
  9722.  
  9723. During exactly-once transactions, SendResponse doesn’t complete until either a TRel
  9724. packet is received from the socket that made the request, or the retry count is
  9725. exceeded.
  9726.  
  9727. Result codes    noErr         No error
  9728.                 badATPSkt     Bad responding socket
  9729.                 noRelErr      No release received
  9730.                 noDataArea    Too many outstanding ATP calls
  9731.                 badBuffNum    Sequence number out of range
  9732.  
  9733. AddResponse function
  9734.  
  9735. Parameter block
  9736.   -->    18    userData    long word  ;user bytes
  9737.   -->    26    csCode      word       ;always addResponse
  9738.   -->    28    atpSocket   byte       ;socket number
  9739.   -->    29    atpFlags    byte       ;control information
  9740.   -->    30    addrBlock   long word  ;response destination
  9741.   -->    34    reqLength   word       ;response size
  9742.   -->    36    reqPointer  pointer    ;pointer to response
  9743.   -->    44    rspNum      byte       ;sequence number
  9744.   -->    46    transID     word       ;transaction ID
  9745.  
  9746. AddResponse sends an additional response packet to a socket that has already been
  9747. sent the initial part of a response via SendResponse. UserData contains the four user
  9748. bytes. ATPSocket contains the socket number from which the response should be sent.
  9749. The end-of-message flag in atpFlags should be set if this response packet is the
  9750. final packet in a transaction composed of a group of packets and the number of responses
  9751. is less than requested. AddrBlock indicates the socket to which the response should
  9752. be sent. ReqLength and reqPointer contain the size (in bytes) and location of the
  9753. response to send; rspNum indicates the sequence number of the response (in the range
  9754. 0 to 7). TransID must contain the transaction ID.
  9755.  
  9756. Warning:  If the transaction is part of an exactly-once transaction, the
  9757.           buffer used in the AddResponse call must not be altered or
  9758.           released until the corresponding SendResponse call has completed.
  9759.  
  9760. Result codes    noErr         No error
  9761.                 badATPSkt     Bad responding socket
  9762.                 noSendResp    AddResponse issued before SendResponse
  9763.                 badBuffNum    Sequence number out of range
  9764.                 noDataArea    Too many outstanding ATP calls
  9765.  
  9766. RelTCB function
  9767.  
  9768. Parameter block
  9769.   -->    26    csCode     word       ;always relTCB
  9770.   -->    30    addrBlock  long word  ;destination of request
  9771.   -->    46    transID    word       ;transaction ID of request
  9772.  
  9773. RelTCB dequeues the specified SendRequest call and returns the result code reqAborted
  9774. for the aborted call. The transaction ID can be obtained from the reqTID field of the
  9775. SendRequest queue entry; see the description of SendRequest for details.
  9776.  
  9777. Result codes    noErr         No error
  9778.                 cbNotFound    ATP control block not found
  9779.                 noDataArea    Too many outstanding ATP calls
  9780.  
  9781. RelRspCB function
  9782.  
  9783. Parameter block
  9784.   -->    26    csCode     word      ;always relRspCB
  9785.   -->    28    atpSocket  byte      ;socket number that request was received on
  9786.   -->    30    addrBlock  long word ;source of request
  9787.   -->    46    transID    word      ;transaction ID of request
  9788.  
  9789. In an exactly-once transaction, RelRspCB cancels the specified SendResponse, without
  9790. waiting for the release timer to expire or a TRel packet to be received. No error is
  9791. returned for the SendResponse call. Whan called to cancel a transaction that isn’t
  9792. using exactly-once service, RelRspCB returns cbNotFound. The transaction ID can be
  9793. obtained from the reqTID field of the SendResponse queue entry; see the description
  9794. of SendResponse for details.
  9795.  
  9796. Result codes    noErr         No error
  9797.                 cbNotFound    ATP control block not found
  9798.  
  9799. _______________________________________________________________________________
  9800.  
  9801. »Name-Binding Protocol
  9802.  
  9803. »Data Structures
  9804.  
  9805. The first two bytes in the NBP header (Figure 13) indicate the type of the packet,
  9806. the number of tuples in the packet, and an NBP packet identifier. You can use the
  9807. following global constants to access these bytes:
  9808.  
  9809.   nbpControl  .EQU    0    ;packet type
  9810.   nbpTCount   .EQU    0    ;tuple count
  9811.   nbpID       .EQU    1    ;packet identifier
  9812.   nbpTuple    .EQU    2    ;start of first tuple
  9813.  
  9814. •••Refer to Figure 13.•••
  9815.  
  9816. Figure 13–NBP Packet
  9817.  
  9818. NBP packets are identified by the following DDP protocol type:
  9819.  
  9820.   nbp         .EQU    2
  9821.  
  9822. NBP uses the following global constants in the nbpControl field to identify NBP
  9823. packets:
  9824.  
  9825.   brRq        .EQU    1    ;broadcast request
  9826.   lkUp        .EQU    2    ;lookup request
  9827.   lkUpReply   .EQU    3    ;lookup reply
  9828.  
  9829. NBP entities are identified by internet address in the form shown in Figure 14 below.
  9830. Entities are also identified by tuples, which include both an internet address and an
  9831. entity name. You can use the following global constants to access information in
  9832. tuples:
  9833.  
  9834.   tupleNet    .EQU    0    ;network number
  9835.   tupleNode   .EQU    2    ;node ID
  9836.   tupleSkt    .EQU    3    ;socket number
  9837.   tupleEnum   .EQU    4    ;used internally
  9838.   tupleName   .EQU    5    ;entity name
  9839.  
  9840. The meta-characters in an entity name can be identified with the following global
  9841. constants:
  9842.  
  9843.   equals      .EQU    '='    ;“wild-card” meta-character
  9844.   star        .EQU    '*'    ;“this zone” meta-character
  9845.  
  9846. •••Refer to Figure 14.•••
  9847.  
  9848. Figure 14–Names Table Entry
  9849.  
  9850. The maximum number of tuples in an NBP packet is given by the following global constant:
  9851.  
  9852.   tupleMax    .EQU    15
  9853.  
  9854. Entity names are mapped to sockets via the names table. Each entry in the names table
  9855. has the structure shown in Figure 14.
  9856.  
  9857. You can use the following global constants to access some of the elements of a names
  9858. table entry:
  9859.  
  9860.   ntLink      .EQU    0    ;pointer to next entry
  9861.   ntTuple     .EQU    4    ;tuple
  9862.   ntSocket    .EQU    7    ;socket number
  9863.   ntEntity    .EQU    9    ;entity name
  9864.  
  9865. The socket number of the names information socket is given by the following global
  9866. constant:
  9867.  
  9868.   nis         .EQU    2
  9869.  
  9870. »Using NBP
  9871.  
  9872. On a Macintosh 128K, before calling any other NBP routines, call the LoadNBP function,
  9873. which reads the NBP code from the system resource file into the application heap.
  9874. (The NBP code is part of the .MPP driver, which has a driver reference number of
  9875. –10.) When you’re finished with NBP and want to reclaim the space its code occupies,
  9876. call UnloadNBP. On a Macintosh 512K or XL, the NBP code is read in when the .MPP
  9877. driver is loaded.
  9878.  
  9879. Warning:  When an application starts up, the application heap is
  9880.           reinitialized; on a Macintosh 128K, this means that the
  9881.           NBP code is lost (and must be reloaded by the next application).
  9882.  
  9883. When an entity wants to communicate via an AppleTalk network, it should call RegisterName
  9884. to place its name and internet address in the names table. When an entity no longer
  9885. wants to communicate on the network, or is being shut down, it should call RemoveName
  9886. to remove its entry from the names table.
  9887.  
  9888. To determine the address of an entity you know only by name, call LookupName, which
  9889. returns a list of all entities with the name you specify. If you already know the
  9890. address of an entity, and want only to confirm that it still exists, call ConfirmName.
  9891. ConfirmName is more efficient than LookupName in terms of network traffic.
  9892.  
  9893. »NBP Routines
  9894.  
  9895. RegisterName function
  9896.  
  9897. Parameter block
  9898.   -->    26    csCode      word     ;always registerName
  9899.   -->    28    interval    byte     ;retry interval
  9900.   <->    29    count       byte     ;retry count
  9901.   -->    30    ntQElPtr    pointer  ;names table element pointer
  9902.   -->    34    verifyFlag  byte     ;set if verify needed
  9903.  
  9904. RegisterName adds the name and address of an entity to the node’s names table. NTQElPtr
  9905. points to a names table entry containing the entity’s name and internet address (in
  9906. the form shown in Figure 14 above). Meta-characters aren’t allowed in the object and
  9907. type fields of the entity name; the zone field, however, must contain the meta-character
  9908. “*”. If verifyFlag is TRUE, RegisterName checks on the network to see if the name is
  9909. already in use, and returns a result code of nbpDuplicate if so. Interval and count
  9910. contain the retry interval in eight-tick units and the retry count. When a retry is
  9911. made, the count field is modified.
  9912.  
  9913. •••Refer to Technical Note #225:•••
  9914.  
  9915. Warning:  The names table entry passed to RegisterName remains the
  9916.           property of NBP until removed from the names table. Don’t
  9917.           attempt to remove or modify it. If you’ve allocated memory
  9918.           using a NewHandle call, you must lock it as long as the name
  9919.           is registered.
  9920.  
  9921. Warning:  VerifyFlag should normally be set before calling RegisterName.
  9922.  
  9923. Result codes    noErr           No error
  9924.                 nbpDuplicate    Duplicate name already exists
  9925.                 nbpNISErr       Error opening names information socket
  9926.  
  9927. LookupName function
  9928.  
  9929. Parameter block
  9930.   -->    26    csCode       word     ;always lookupName
  9931.   -->    28    interval     byte     ;retry interval
  9932.   <->    29    count        byte     ;retry count
  9933.   -->    30    entityPtr    pointer  ;pointer to entity name
  9934.   -->    34    retBuffPtr   pointer  ;pointer to buffer
  9935.   -->    38    retBuffSize  word     ;buffer size in bytes
  9936.   -->    40    maxToGet     word     ;matches to get
  9937.   <--    42    numGotten    word     ;matches found
  9938.  
  9939. LookupName returns the addresses of all entities with a specified name. EntityPtr
  9940. points to the entity’s name (in the form shown in Figure 14 above). Meta-characters
  9941. are allowed in the entity name. RetBuffPtr and retBuffSize contain the location and
  9942. size of an area of memory in which the tuples describing the entity names and their
  9943. corresponding addresses should be returned. MaxToGet indicates the maximum number of
  9944. matching names to find addresses for; the actual number of addresses found is returned
  9945. in numGotten. Interval and count contain the retry interval and the retry count.
  9946. LookupName completes when either the number of matches is equal to or greater than
  9947. maxToGet, or the retry count has been exceeded. The count field is decremented for
  9948. each retransmission.
  9949.  
  9950. Note:  NumGotten is first set to 0 and then incremented with each match
  9951.        found. You can test the value in this field, and can start examining
  9952.        the received addresses in the buffer while the lookup continues.
  9953.  
  9954. Result codes    noErr         No error
  9955.                 nbpBuffOvr    Buffer overflow
  9956.  
  9957. ConfirmName function
  9958.  
  9959. Parameter block
  9960.   -->    26    csCode       word     ;always confirmName
  9961.   -->    28    interval     byte     ;retry interval
  9962.   <->    29    count        byte     ;retry count
  9963.   -->    30    entityPtr    pointer  ;pointer to entity name
  9964.   -->    34    confirmAddr  pointer  ;entity address
  9965.   <--    38    newSocket    byte     ;socket number
  9966.  
  9967. ConfirmName confirms that an entity known by name and address still exists (is still
  9968. entered in the names directory). EntityPtr points to the entity’s name
  9969. (in the form shown in Figure 14 above). ConfirmAddr specifies the address to confirmed.
  9970. No meta-characters are allowed in the entity name. Interval and count contain the
  9971. retry interval and the retry count. The socket number of the entity is returned in
  9972. newSocket. ConfirmName is more efficient than LookupName in terms of network traffic.
  9973.  
  9974. Result codes    noErr           No error
  9975.                 nbpConfDiff     Name confirmed for different socket
  9976.                 nbpNoConfirm    Name not confirmed
  9977.  
  9978. RemoveName function
  9979.  
  9980. Parameter block
  9981.   -->    26    csCode     word     ;always removeName
  9982.   -->    30    entityPtr  pointer  ;pointer to entity name
  9983.  
  9984. RemoveName removes an entity name from the names table of the given entity’s node.
  9985.  
  9986. Result codes    noErr          No error
  9987.                 nbpNotFound    Name not found
  9988.  
  9989. LoadNBP function
  9990.  
  9991. Parameter block
  9992.   -->    26    csCode  word  ;always loadNBP
  9993.  
  9994. On a Macintosh 128K, LoadNBP reads the NBP code from the system resource file into
  9995. the application heap; on a Macintosh 512K or XL it has no effect.
  9996.  
  9997. Result codes    noErr    No error
  9998.  
  9999. UnloadNBP function
  10000.  
  10001. Parameter block
  10002.   -->    26    csCode  word  ;always unloadNBP
  10003.  
  10004. On a Macintosh 128K, UnloadNBP makes the NBP code purgeable; the space isn’t actually
  10005. released by the Memory Manager until necessary. On a Macintosh 512K or XL, UnloadNBP
  10006. has no effect.
  10007.  
  10008. Result codes    noErr    No error
  10009.  
  10010. _______________________________________________________________________________
  10011.  
  10012.  
  10013. æKY Extended…Protocol…Package…Driver
  10014. æC »EXTENDED PROTOCOL PACKAGE DRIVER                         AppleTalkManager
  10015. _______________________________________________________________________________
  10016.  
  10017. The Extended Protocol Package (XPP) driver is intended to implement several AppleTalk
  10018. communication protocols in the same package for ease of use.  The
  10019. .XPP driver currently consists of two modules that operate on two levels: the low-level
  10020. module implements the workstation side of AppleTalk Session Protocol, and the high-level
  10021. module implements a small portion of the workstation side of the AppleTalk Filing
  10022. Protocol.
  10023.  
  10024. This driver adds functionality to the AppleTalk manager by providing services additional
  10025. to those provided in the .MPP and .ATP drivers.  Figure 2 shows the Macintosh AppleTalk
  10026. drivers and the protocols accessible through each driver.
  10027.  
  10028. The .XPP driver maps an AFP call from the client workstation into one or more ASP
  10029. calls. .XPP provides one client-level call for AFP.
  10030.  
  10031. The implementation of AFP in the .XPP driver is very limited.  Most calls are a very
  10032. simple one-to-one mapping from an AFP call to an ASP command without any interpretation
  10033. of the syntax of the AFP command by the .XPP driver.  Refer to the “Mapping AFP
  10034. Commands” section of this chapter for further information.
  10035.  
  10036. _______________________________________________________________________________
  10037.  
  10038. »Version
  10039.  
  10040. The .XPP driver supports ASP Version (hex) $100, as described in Inside AppleTalk.
  10041.  
  10042. _______________________________________________________________________________
  10043.  
  10044. »Error Reporting
  10045.  
  10046. Errors are returned by the .XPP driver in the ioResult field of the Device Manager
  10047. Control calls.
  10048.  
  10049. The error conditions reported by the .XPP driver may represent the unsuccessful
  10050. completion of a routine in more than just one process involved in the interaction of
  10051. the session.   System-level, .XPP driver, AppleTalk, and server errors can all turn
  10052. up in the ioResult field.
  10053.  
  10054. AFP calls return codes indicating the unsuccessful completion of AFP commands in the
  10055. Command Result field of the parameter block (described below).
  10056.  
  10057. An application using the .XPP driver should  respond appropriately to error conditions
  10058. reported from the different parts of the interaction.  As shown in Figure 3, the
  10059. following errors can be returned in the ioResult field:
  10060.  
  10061.   1.  System-level errors
  10062.  
  10063.       System errors returned by the .XPP driver indicate such conditions
  10064.       as the driver not being open or a specific system call not being
  10065.       supported. For a complete list of result codes returned by the
  10066.       Macintosh system software, refer to Appendix A.
  10067.  
  10068.   2.  XPP errors (for example, “Session not opened”)
  10069.  
  10070.       The .XPP driver can also return errors resulting from its own
  10071.       activity (for example, the referenced session isn’t open).  The
  10072.       possible .XPP driver errors returned are listed in the .XPP driver
  10073.       results codes section with each function that can return the code.
  10074.  
  10075.   3.  AppleTalk Errors (returned from lower-level protocols)
  10076.  
  10077.       .XPP may also return errors from lower-level protocols (for example,
  10078.       “Socket not open”).  Possible error conditions and codes are described
  10079.       elsewhere in this chapter.
  10080.  
  10081.   4.  An  ASP-specific error could be returned from an ASP server in
  10082.       response to a failed OpenSession call.  Errors of this type, returned
  10083.       by the server to the workstation, are documented both in Inside
  10084.       AppleTalk, section 11,  “AppleTalk Session Protocol”, and in the .XPP
  10085.       driver results code section of this chapter.
  10086.  
  10087.   5.  The AppleTalk Filing Protocol defines errors that are returned from
  10088.       the server to the workstation client.  These errors are returned in
  10089.       the cmdResult field of the parameter block (error type 5 in Figure 15).
  10090.       This field is valid if no system-level error is returned by the call.
  10091.       Note that at the ASP level, the cmdResult field is client-defined data
  10092.       and may not be an error code.
  10093.  
  10094. •••Refer to Figure 15.•••
  10095.  
  10096. Figure 15–Error Reporting
  10097.  
  10098. _______________________________________________________________________________
  10099.  
  10100. ».XPP Driver Functions Overview
  10101.  
  10102. The paragraphs below describe the implementation of ASP in the .XPP driver.  For more
  10103. detailed information about ASP, refer to Inside AppleTalk, Section 11, “AppleTalk
  10104. Session Protocol (ASP)”.
  10105.  
  10106. »Using AppleTalk Name Binding Protocol
  10107.  
  10108. A server wishing to advertise its service on the AppleTalk network calls ATP to open
  10109. an ATP responding socket known as the session listening socket (SLS).  The server
  10110. then calls the Name Binding Protocol (NBP) to register a name on this socket.  At
  10111. this point, the server calls the server side of ASP to pass it the address of the
  10112. SLS.  Then,  the server starts listening on the SLS for session opening requests
  10113. coming over the network.
  10114.  
  10115. »Opening and Closing Sessions
  10116.  
  10117. When a workstation wishes to access a server, the workstation must call NBP to discover
  10118. the SLS for that server.  Then the workstation calls ASP to open a session with that
  10119. server.
  10120.  
  10121. After determining the SLS (address) of the server, the workstation client issues an
  10122. OpenSession (or AFPLogin) call to open a session with that server.  As a result of
  10123. this call, ASP sends a special OpenSession packet (an ATP request) to the SLS; this
  10124. packet carries the address of a workstation socket for use in the session.   This
  10125. socket is referred to as the workstation session socket (WSS).  If the server is
  10126. unable to set up the session, it returns an error.  If the request is successful, the
  10127. server returns no error, and the session is opened.  The open session packet also
  10128. contains a version number so that both ends can verify that they are speaking the
  10129. same version of ASP.
  10130.  
  10131. The AbortOS function can be used to abort an outstanding OpenSession request before
  10132. it has completed.
  10133.  
  10134. The workstation client closes the session by issuing a CloseSession (or AFPLogout). 
  10135. The CloseSession call aborts any calls that are active on the session and closes the
  10136. session.  The session can also be closed by the server or by ASP itself, such as when
  10137. one end of the session fails.  The CloseAll call (which should be used with care)
  10138. aborts every session that the driver has active.
  10139.  
  10140. »Session Maintenance
  10141.  
  10142. A session will remain open until it is explicitly terminated by the ASP client at
  10143. either end or until one of the sessions ends, fails, or becomes unreachable.
  10144.  
  10145. »Commands on an Open Session
  10146.  
  10147. Once a session has been opened, the workstation client can send a sequence of commands
  10148. over the session to the server end.  The commands are delivered in the same order as
  10149. they are issued at the workstation end, and replies to the commands are returned to
  10150. the workstation end.
  10151.  
  10152. Three types of commands can be made on an open session.  These commands are UserCommand,
  10153. UserWrite, and AFPCall functions described in the following paragraphs.
  10154.  
  10155. UserCommand calls are similar to ATP requests.  The workstation client sends a command
  10156. (included in a variable size command block) to the server client requesting it to
  10157. perform a particular function and send back a variable size command reply.  Examples
  10158. of such commands vary from a request to open a particular file on a file server, to
  10159. reading a certain range of bytes from a device.  In the first case, a small amount of
  10160. reply data is returned; in the second case a multiple-packet reply might be generated.
  10161.  
  10162. The .XPP driver does not interpret the command block or in any way participate in
  10163. executing the command’s function.  It simply conveys the command block, included in a
  10164. higher-level format, to the server end of the session, and returns the command reply
  10165. to the workstation-end client.  The command reply consists of a four-byte command
  10166. result and a variable size command reply block.
  10167.  
  10168. UserWrite allows the workstation to convey blocks of data to the server.  UserWrite
  10169. is used to transfer a variable size block of data to the server end of the session
  10170. and to receive a reply.
  10171.  
  10172. The AFPCall function provides a mechanism for passing an AFP command to the server
  10173. end of an open session and receiving a reply.  The first byte of the AFPCall command
  10174. buffer contains the code for the AFP command that is to be passed to the server for
  10175. execution.  Most AFP calls are implemented through a very simple one-to-one mapping
  10176. that takes the call and makes an ASP command out of it.
  10177.  
  10178. The AFPCall function can have one of four different, but very similar, formats.
  10179.  
  10180. »Getting Server Status Information
  10181.  
  10182. ASP provides a service to allow its workstation clients to obtain a block of service
  10183. status information from a server without the need for opening a session.   The GetStatus
  10184. function  returns a status block from the server identified by the indicated address.
  10185.  ASP does not impose any structure on the status block.  This structure is defined by
  10186. the protocol above ASP.
  10187.  
  10188. »Attention Mechanism
  10189.  
  10190. Attentions are defined in ASP as a way for the server to alert the workstation of
  10191. some event or critical piece of information.  The ASP OpenSession and AFPLogin calls
  10192. include a pointer to an attention routine in their parameter blocks.  This attention
  10193. routine is called by the .XPP driver when it receives an attention from the server
  10194. and also when the session is closing as described below.
  10195.  
  10196. In addition, upon receiving an OpenSession call or AFPLogin call, the .XPP driver
  10197. sets the first two bytes of the session control block (SCB) to zero.  When the .XPP
  10198. driver receives an attention, the first two bytes of the SCB are set to the attention
  10199. bytes from the packet (which are always nonzero).
  10200.  
  10201. Note: A higher-level language such as Pascal may not wish to have a low-level
  10202.       attention routine called.  A Pascal program can poll the attention bytes,
  10203.       and if they are ever nonzero, the program will know that an attention
  10204.       has come in.  (It would then set the attention bytes back to zero.)
  10205.       Of course, two or more attentions could be received between successive
  10206.       polls, and only the last one would be recorded.
  10207.  
  10208. The .XPP driver also calls the attention routine when the session is closed by either
  10209. the server, workstation, or ASP itself (if the ASP session times out).  In these
  10210. cases, the attention bytes in the SCB are unchanged.
  10211.  
  10212. »The Attention Routine
  10213.  
  10214. The attention routine is called at interrupt level and must observe interrupt conventions.
  10215. Specifically, the interrupt routine can change registers A0 through A3 and D0 through
  10216. D3 and it must not make any Memory Manager calls.
  10217.  
  10218. It will be called with
  10219.  
  10220.   •  D0 (word) equal to the SessRefnum for that session (see OpenSession
  10221.      Function)
  10222.   •  D1 (word) equal to the attention bytes passed by the server (or zero
  10223.      if the session is closing)
  10224.  
  10225. Return with an RTS (return from subroutine) to resume normal execution.
  10226.  
  10227. The next section describes the calls that can be made to the .XPP driver.
  10228.  
  10229. _______________________________________________________________________________
  10230.  
  10231.  
  10232. æKY Calling…the….XPP…Driver
  10233. æC »CALLING THE .XPP DRIVER                                  AppleTalkManager
  10234. _______________________________________________________________________________
  10235.  
  10236. This section describes how to use the .XPP driver and how to call the .XPP driver
  10237. routines from assembly language and Pascal.
  10238.  
  10239. _______________________________________________________________________________
  10240.  
  10241. »Using XPP
  10242.  
  10243. The .XPP driver implements the workstation side of ASP and provides a mechanism for
  10244. the workstation to send AppleTalk Filing Protocol (AFP) commands to the server.
  10245.  
  10246. »Allocating Memory
  10247.  
  10248. Every call to the .XPP driver requires the caller to pass in whatever memory is
  10249. needed by the driver for the call, generally at the end of the queue element. When a
  10250. session is opened, the memory required for maintenance of that session
  10251. (that is, the Session Control Block) is also passed in.
  10252.  
  10253. For standard Device Manager calls, a queue element of a specific size equal to IOQElSize
  10254. is allocated.  When issuing many calls to XPP, it is the caller’s responsibility to
  10255. allocate a queue element that is large enough to accommodate the .XPP driver’s requirements
  10256. for executing that call, as defined below.  Once allocated, that memory can’t be
  10257. modified until the call completes.
  10258.  
  10259. »Opening the .XPP Driver
  10260.  
  10261. To open the .XPP driver, issue a Device Manager Open call.  (Refer to the Device
  10262. Manager chapter.)  The name of the .XPP driver is '.XPP'.  The original Macintosh
  10263. ROMs require that .XPP be opened only once. With new ROMs, the .XPP unit number can
  10264. always be obtained through an Open call.  With old ROMs only, the .XPP unit number
  10265. must be hard coded to XPPUnitNum (40) since only one Open call can be issued to the
  10266. driver.
  10267.  
  10268. The .XPP driver cannot be opened unless AppleTalk is open.  The application must
  10269. ensure that the .MPP and .ATP drivers are opened, as described earlier in this chapter.
  10270.  
  10271. The xppLoaded bit (bit 5) in the PortBUse byte in low memory indicates whether or not
  10272. the .XPP driver is open.
  10273.  
  10274. »Example
  10275.  
  10276. The following is an example of the procedure an application might use to open the
  10277. .XPP driver.
  10278.  
  10279. ;    Routine: OpenXPP
  10280. ;
  10281. ;        Open the .XPP driver and return the driver refNum for it.
  10282. ;
  10283. ;        Exit:    D0 = error code (ccr's set)
  10284. ;                 D1 = XPP driver refNum (if no errors)
  10285. ;
  10286. ;        All other registers preserved
  10287. ;
  10288. xppUnitNum    EQU    40                 ;default XPP driver number
  10289. xppTfRNum     EQU    -(xppUnitNum+1)    ;default XPP driver refNum
  10290.  
  10291. OpenXPP
  10292.     MOVE.L    A0-A1/D2,-(SP)            ;save registers
  10293.     MOVE      ROM85,D0                  ;check ROM type byte
  10294.     BPL.S     @10                       ;branch if >=128K ROMs
  10295.     BTST      #xppLoadedBit,PortBUse    ;is the XPP driver open already?
  10296.     BEQ.S     @10                       ;if not open, then branch to Open code
  10297.     MOVE      #xppTfRNum,D1             ;else use this as driver refnum
  10298.     MOVEQ     #0,D0                     ;set noErr
  10299.     BRA.S     @90                       ;and exit
  10300. ;
  10301. ; XPP driver not open. Make an _Open call to it. If using a 128K
  10302. ; ROM machine and the driver is already open, we will make another
  10303. ; Open call to it just so we get the correct driver refNum.
  10304. ;
  10305. @10 SUB       #ioQElSize,SP             ;allocate temporary param block
  10306.     MOVE.L    SP,A0                     ;A0 -> param block
  10307.     LEA       XPPName, A1               ;A1 -> XPP (ASP/AFP) driver name
  10308.     MOVE.L    A1,ioFileName(A0)         ;driver name into param block
  10309.     CLR.B     ioPermssn(A0)             ;clear permissions byte
  10310.     _Open
  10311.     MOVE      ioRefNum(A0),D1           ;D1=driver refNum (invalid if error)
  10312.     ADD       #ioQElSize,SP             ;deallocate temp param block
  10313. @90 MOVE.L    (SP)+,A0-A1/D2            ;restore registers
  10314.     TST       D0                        ;error? (set ccr's)
  10315.     RTS
  10316.     
  10317. XPPName  DC.B  4                        ;length of string
  10318.          DC.B  '.XPP'                   ;driver name
  10319.  
  10320. From Pascal, XPP can be opened through the OpenXPP call, which returns the driver’s
  10321. reference number:
  10322.  
  10323. FUNCTION OpenXPP (VAR xppRefnum: INTEGER) : OSErr;
  10324.  
  10325. »Open Errors
  10326.  
  10327. Errors returned when calling the Device Manager Open routine if the function does not
  10328. execute properly include the following:
  10329.  
  10330.   •  errors returned by System
  10331.   •  portInUse is returned if the AppleTalk port is in use by a driver
  10332.      other than AppleTalk or if AppleTalk is not open.
  10333.  
  10334. »Closing the .XPP Driver
  10335.  
  10336. To close the .XPP driver, call the Device Manager Close routine.
  10337.  
  10338. Warning:  There is generally no reason to close the driver.  Use this
  10339.           call sparingly, if at all.  This call should generally be used
  10340.           only by system-level applications.
  10341.  
  10342. »Close Errors
  10343.  
  10344. Errors returned when calling the Device Manager Close routine if the function does
  10345. not execute properly include the following:
  10346.  
  10347.   •  errors returned by System
  10348.   •  closeErr (new ROMs only) is returned if you try to close the driver
  10349.      and there are sessions active through that driver.  When sessions are
  10350.      active, closeErr is returned and the driver remains open.
  10351.   •  on old ROMs the driver is closed whether or not sessions are active
  10352.      and no error is returned. Results are unpredictable if sessions are
  10353.      still active.
  10354.  
  10355. »Session Control Block
  10356.  
  10357. The session control block (SCB) is a nonrelocatable block of data passed by the
  10358. caller to XPP upon session opening. XPP reserves this block for use in maintaining an
  10359. open session.   The SCB size is defined by the constant scbMemSize.  The SCB is a
  10360. locked block, and as long as the session is open, the SCB cannot be modified in any
  10361. way by the application.  There is one SCB for each open session. This block can be
  10362. reused once a CloseSess call is issued and completed for that session or when the
  10363. session is indicated as closed.
  10364.  
  10365. _______________________________________________________________________________
  10366.  
  10367. »How to Access the .XPP Driver
  10368.  
  10369. This section contains information for programmers using Pascal and assembly-language
  10370. routines.
  10371.  
  10372. All .XPP driver routines can be executed either synchronously (meaning that the
  10373. application can’t continue until the routine is completed) or asynchronously
  10374. (meaning that the application is free to perform other tasks while the routine is
  10375. executing).
  10376.  
  10377. XPP calls are made from Pascal in the same manner as MPP and ATP calls, with the
  10378. exception that when making XPP calls the caller must set the XPP driver’s refnum.  
  10379. This refnum is returned in the XPPOpen call’s parameter block.
  10380.  
  10381. A Pascal variant record has been defined for all XPP calls.  This parameter block is
  10382. detailed in the “.XPP Driver Parameter Block Record” section below.  The first four
  10383. fields (which are the same for all calls) are automatically filled in by the device
  10384. manager.  The csCode field is automatically filled in by Pascal, depending on which
  10385. call is being made.  The caller must, however, set the ioRefnum field to XPP’s reference
  10386. number, as returned in the OpenXPP call.  The ioVRefnum field is unused.
  10387.  
  10388. Note that the parameter block is defined so as to be the maximum size used by any
  10389. call.  Different calls take different size parameter blocks, each call requiring a
  10390. certain minimum size.  Callers are free to abbreviate the parameter block where
  10391. appropriate.
  10392.  
  10393. »General
  10394.  
  10395. With each routine, a list of the parameter block fields used by the call is also
  10396. given.  All routines are invoked by Device Manager Control calls with the csCode
  10397. field equal to the code corresponding to the function being called.  The number next
  10398. to each field name indicates the byte offset of the field from the start of the
  10399. parameter block pointed to by A0; only assembly-language programmers need to be
  10400. concerned with it.  An arrow next to each parameter name indicates whether it’s an
  10401. input, output, or input/output parameter:
  10402.  
  10403. Arrow    Meaning
  10404.   <--    Parameter is passed
  10405.   <--    Parameter is returned
  10406.   <->    Parameter is passed and returned
  10407.  
  10408. All Device Manager Control calls return an integer result code in the ioResult field.
  10409.  Each routine description lists all the applicable result codes, along with a short
  10410. description of what the result code means.  Refer to the section
  10411. “XPP Driver Result Codes” for an alphabetical list of result codes returned by the
  10412. .XPP driver.
  10413.  
  10414. Each routine description includes a Pascal form of the call.   Pascal calls to the
  10415. .XPP Driver are of the form:
  10416.  
  10417. FUNCTION XPPCall (paramBlock: XPPParmBlkPtr,async: BOOLEAN) : OSErr;
  10418.  
  10419. XPPCall is the name of the routine.
  10420.  
  10421. The parameter paramBlock points to the actual I/O queue element used in the
  10422. _Control call, filled in by the caller with the parameters of the routine.
  10423.  
  10424. The parameter async indicates whether or not the call should be made asynchronously. 
  10425.  If async is TRUE, the call is executed asynchronously; otherwise the call is executed
  10426. synchronously.
  10427.  
  10428. The routine returns a result code of type OSErr.
  10429.  
  10430. ».XPP Driver Parameter Block Record
  10431.  
  10432. XPPParamBlock = PACKED RECORD
  10433.     qLink:         QElemPtr;  {next queue entry}
  10434.     qType:         INTEGER;   {queue type}
  10435.     ioTrap:        INTEGER;   {routine trap}
  10436.     ioCmdAddr:     Ptr;       {routine address}
  10437.     ioCompletion:  ProcPtr;   {completion routine}
  10438.     ioResult:      OSErr;     {result code}
  10439.     cmdResult:     LONGINT;   {command result (ATP user bytes) [long]}
  10440.     ioVRefNum:     INTEGER;   {volume reference or drive number)
  10441.     ioRefNum:      INTEGER;   {driver reference number)
  10442.     csCode:        INTEGER;   {Call command code}
  10443.     CASE XPPPrmBlkType OF
  10444.       ASPAbortPrm:
  10445.         (abortSCBPtr:    Ptr);      {SCB pointer for AbortOS [long]}
  10446.       ASPSizeBlk:
  10447.         (aspMaxCmdSize:  INTEGER;   {for SPGetParms [word]
  10448.         aspQuantumSize:  INTEGER;   {for SPGetParms [word]}
  10449.         numSesss:        INTEGER);  {for SPGetParms [word]}
  10450.       XPPPrmBlk:
  10451.         (sessRefnum:     INTEGER;   {offset to session refnum [word]}
  10452.         aspTimeout:      Byte;      {timeout for ATP [byte]}
  10453.         aspRetry:        Byte;      {retry count for ATP [byte]}
  10454.         CASE XPPSubPrmType OF
  10455.           ASPOpenPrm:
  10456.             (serverAddr:    AddrBlock;  {server address block [longword]}
  10457.             scbPointer:     Ptr;        {SCB pointer [longword]}
  10458.             attnRoutine:    Ptr);       {attention routine pointer [long]}
  10459.           ASPSubPrm:
  10460.             (cbSize:        INTEGER;    {command block size [word]}
  10461.             cbPtr:          Ptr;        {command block pointer [long]}
  10462.             rbSize:         INTEGER;    {reply buffer size [word]}
  10463.             rbPtr:          Ptr;        {reply buffer pointer [long]}
  10464.             CASE XPPEndPrmType OF
  10465.               AFPLoginPrm:
  10466.                 (afpAddrBlock:     AddrBlock;    {address block in}
  10467.                                                  { AFPlogin [long]}
  10468.                 afpSCBPtr:         Ptr;          {SCB pointer in }
  10469.                                                  { AFPlogin [long]}
  10470.                 afpAttnRoutine:    Ptr);         {attn routine pointer }
  10471.                                                  { in AFPlogin}
  10472.               ASPEndPrm:
  10473.                 (wdSize:           INTEGER;      {write data size [word]}
  10474.                 wdPtr:             Ptr;          {write data pointer [long]}
  10475.                 ccbStart:          ARRAY[0..295] OF Byte)));   {CCB memory }
  10476.                                                                { for driver}
  10477.      {Write max size(CCB) = 296; all other calls = 150}
  10478.      END;
  10479.  
  10480. _______________________________________________________________________________
  10481.  
  10482. »AppleTalk Session Protocol Functions
  10483.  
  10484. This section contains descriptions of the .XPP driver functions that you can call. 
  10485. Each function description shows the required parameter block fields, their offsets
  10486. within the parameter block and a brief definition of the field.  Possible result
  10487. codes are also described.
  10488.  
  10489. »Note on Result Codes
  10490.  
  10491. An important distinction exists between the aspParamErr and aspSessClose  result
  10492. codes that may be returned by the .XPP driver.
  10493.  
  10494. When the driver returns aspParamErr to a call that takes as an input a session reference
  10495. number, the session reference number does not relate to a valid open session.  There
  10496. could be several reasons for this, such as the workstation or server end closed the
  10497. session or the server end of the session died.
  10498.  
  10499. The aspSessClosed result code indicates that even though the session reference number
  10500. relates to a valid session, that particular session is in the process of closing down
  10501. (although  the session is not yet closed).
  10502.  
  10503. FUNCTION ASPOpenSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10504.  
  10505. Parameter block
  10506.   -->    26    csCode       word       Always ASPOpenSess
  10507.   -->    28    sessRefnum   word       Session reference number
  10508.   -->    30    aspTimeout   byte       Retry interval in seconds
  10509.   -->    31    aspRetry     byte       Number of retries
  10510.   -->    32    serverAddr   long word  Server socket address
  10511.   -->    36    scbPointer   pointer    Pointer to session control block
  10512.   -->    40    attnRoutine  pointer    Pointer to attention routine
  10513.  
  10514. ASPOpenSession initiates (opens) a session between the workstation and a server.  The
  10515. required parameter block is shown above.  A brief definition of the fields follows.
  10516.  
  10517. SessRefnum is a unique number identifying the open session between the workstation
  10518. and the server.  The SessRefnum is returned when the function completes successfully
  10519. and is used in all calls to identify the session.
  10520.  
  10521. ASPTimeOut is the interval in seconds between retries of the open session request.
  10522.  
  10523. ASPRetry is the number of retries that will be attempted.
  10524.  
  10525. ServerAddr is the network identifier or address of the socket on which the server is
  10526. listening.
  10527.  
  10528. SCBPointer points to a nonrelocatable block of data for the session control block
  10529. (SCB) that the .XPP driver reserves for use in maintaining an open session.   The SCB
  10530. size is defined by the constant scbMemSize.  The SCB is a locked block and as long as
  10531. the session is open, the SCB cannot be modified in any way by the application.  There
  10532. is one SCB for each open session.  This block can be reused when a CloseSess call is
  10533. issued and completed for that session, or when the session is indicated as closed
  10534. through return of aspParamErr as the result of a call for that session.
  10535.  
  10536. AttnRoutine is a pointer to a routine that is invoked if an attention from the server
  10537. is received, or upon session closing.  If this pointer is equal to zero, no attention
  10538. routine will be invoked.
  10539.  
  10540. Result codes    aspNoMoreSess    Driver cannot support another session
  10541.                 aspParamErr      Server returned bad (positive) error code    
  10542.                 aspNoServers     No servers at that address, or the server
  10543.                                  did not respond to the request
  10544.                 reqAborted       OpenSess was aborted by an AbortOS
  10545.                 aspBadVersNum    Server cannot support the offered 
  10546.                                  version number
  10547.                 aspServerBusy    Server cannot open another session
  10548.  
  10549. Note: The number of sessions that the driver is capable of supporting
  10550.       depends on the machine that the driver is running on. 
  10551.  
  10552. FUNCTION ASPCloseSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10553.  
  10554. Parameter block
  10555.   -->    26    csCode      word  Always ASPCloseSession
  10556.   -->    28    sessRefnum  word  Session reference number
  10557.  
  10558. ASPCloseSession closes the session identified by the sessRefnum returned in the
  10559. ASPOpenSession call.  ASPCloseSession aborts any calls that are active on the session,
  10560. closes the session, and calls the attention routine, if any, with an attention code
  10561. of zero (zero is invalid as a real attention code).
  10562.  
  10563. Result codes    aspParamErr      Parameter error, indicates an invalid
  10564.                                  session reference number
  10565.                 aspSessClosed    Session already in process of closing
  10566.  
  10567. FUNCTION ASPAbortOS (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10568.  
  10569. Parameter block
  10570.   -->    26    csCode            word     Always ASPAbortOS
  10571.   -->    28    abortSCBPointer   pointer  Pointer to session control block
  10572.  
  10573. ASPAbortOS aborts a pending (not yet completed) ASPOpenSession call.  The aborted
  10574. ASPOpenSession call will return a reqAborted error.
  10575.  
  10576. AbortSCBPointer points to the original SCB used in the the pending ASPOpenSession
  10577. call.
  10578.  
  10579. Result codes    cbNotFound    SCB not found, no outstanding open session
  10580.                               to be aborted.
  10581.                               Pointer did not point to an open session SCB.
  10582.  
  10583. FUNCTION ASPGetParms (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
  10584.  
  10585. Parameter block
  10586.   -->    26    csCode          word  Always ASPGetParms
  10587.   -->    28    aspMaxCmdSize   word  Maximum size of command block
  10588.   -->    30    aspQuantumSize  word  Maximum data size
  10589.   -->    32    numSesss        word  Number of sessions
  10590.  
  10591. ASPGetParms returns three ASP parameters.  This call does not require an open session.
  10592.  
  10593. ASPMaxCmdSize is the maximum size of a command that can be sent to the server.
  10594.  
  10595. ASPQuantumSize is the maximum size of data that can be transferred to the server in a
  10596. Write request or from the server in a command reply.
  10597.  
  10598. NumSess is the number of concurrent sessions supported by the driver.
  10599.  
  10600. FUNCTION ASPCloseAll (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10601.  
  10602. Parameter block
  10603.   -->    26    csCode  word  Always ASPCloseAll
  10604.  
  10605. ASPCloseAll closes every session that the driver has active, aborting all active
  10606. requests and invoking the attention routines where provided.  This call should be
  10607. used carefully.  ASPCloseAll can be used as a system level resource for making sure
  10608. all sessions are closed prior to closing the driver.
  10609.  
  10610. FUNCTION ASPUserWrite (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
  10611.  
  10612. Parameter block
  10613.   -->    18    cmdResult   long word  ASP command result
  10614.   -->    26    csCode      word       Always UserWrite
  10615.   -->    28    sessRefnum  word       Session reference number
  10616.   -->    30    aspTimeout  byte       Retry interval in seconds
  10617.   -->    32    cbSize      word       Command block size
  10618.   -->    34    cbPtr       pointer    Command block pointer
  10619.   <->    38    rbSize      word       Reply buffer size and reply size
  10620.   -->    40    rbPtr       pointer    Reply buffer pointer
  10621.   <->    44    wdSize      word       Write data size
  10622.   -->    46    wdPtr       pointer    Write data pointer
  10623.   -->    50    ccbStart    record     Start of memory for CCB
  10624.  
  10625. ASPUserWrite transfers data on a session.  ASPUserWrite is one of the two main calls
  10626. that can be used to transfer data on an ASP session.  The other call that performs a
  10627. similar data transfer  is ASPUserCommand described below.  The ASPUserWrite command
  10628. returns data in two different places.  Four bytes of data are returned in the cmdResult
  10629. field and a variable size reply buffer is also returned.
  10630.  
  10631. CmdResult is four bytes of data returned by the server.
  10632.  
  10633. SessRefnum is the session reference number returned in the ASPOpenSession call.
  10634.  
  10635. ASPTimeOut is the interval in seconds between retries of the call.  Notice that there
  10636. is no aspRetry field (retries are infinite).  The command will be retried at the
  10637. prescribed interval until completion or the session is closed.
  10638.  
  10639. CBSize is the size in bytes of the command data that is to be written on the session.
  10640.  The size of the command block must not exceed the value of aspMaxCmdSize returned by
  10641. the ASPGetParms call. Note that this buffer is not the data to be written by the
  10642. command but only the data of the command itself.
  10643.  
  10644. CBPtr points to the command data.
  10645.  
  10646. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  10647. command.  RBSize is also returned and indicates the size of the reply that was actually
  10648. returned.
  10649.  
  10650. RBPtr points to the reply buffer.
  10651.  
  10652. WDSize is passed and indicates the size of the write data in bytes to be sent by the
  10653. command.  WDSize is also returned and indicates the size of the write data that was
  10654. actually written.
  10655.  
  10656. WDPointer points to the write data buffer.
  10657.  
  10658. CCBStart is the start of the memory to be used by the .XPP driver for the command
  10659. control block.  The size of this block is equal to a maximum of 296 bytes.  To determine
  10660. the exact requirement, refer to the CCB Sizes section of this document.
  10661.  
  10662. Result codes     aspParamErr       Invalid session number, session has
  10663.                                    been closed
  10664.                  aspSizeErr        Command block size is bigger than MaxCmdSize
  10665.                  aspSessClosed     Session is closing
  10666.                  aspBufTooSmall    Reply is bigger than response buffer;
  10667.                                    the buffer will be filled, data will
  10668.                                    be truncated
  10669.  
  10670. FUNCTION ASPUserCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10671.  
  10672. Parameter block
  10673.   -->    18    cmdResult   long word  ASP command result
  10674.   -->    26    csCode      word       Always ASPUserCommand
  10675.   -->    28    sessRefnum  word       Session number
  10676.   -->    30    aspTimeout  byte       Retry interval in seconds
  10677.   -->    32    cbSize      word       Command block size
  10678.   -->    34    cbPtr       pointer    Command block pointer
  10679.   <->    38    rbSize      word       Reply buffer and reply size
  10680.   -->    40    rbPtr       pointer    Reply buffer pointer
  10681.   -->    50    ccbStart    record     Start of memory for CCB
  10682.  
  10683. ASPUserCommand is used to send a command to the server on a session.
  10684.  
  10685. SessRefnum is the session reference number returned in the ASPOpenSession call.
  10686.  
  10687. ASPTimeOut is the interval in seconds between retries of the call.  Notice that there
  10688. is no aspRetry field (retries are infinite).  The command will be retried at the
  10689. prescribed interval until completion or the session is closed.
  10690.  
  10691. CBSize is the size in bytes of the block of data that contains the command to be sent
  10692. to the server on the session.  The size of the command block must not exceed the
  10693. value of aspMaxCmdSize returned by the ASPGetParms call.
  10694.  
  10695. CBPointer points to the block of data containing the command that is to be sent to
  10696. the server on the session.
  10697.  
  10698. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  10699. command.  RBSize is also returned and indicates the size of the reply that was actually
  10700. returned.
  10701.  
  10702. RBPtr points to the reply buffer.
  10703.  
  10704. CCBStart is the start of the memory to be used by the .XPP driver for the command
  10705. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  10706. the exact requirement refer to the CCB Sizes section of this document.
  10707.  
  10708. Result codes     aspParamErr       Invalid session number, session has
  10709.                                    been closed
  10710.                  aspSizeErr        Command block size is bigger than MaxCmdSize
  10711.                  aspSessClosed     Session is closing
  10712.                  aspBufTooSmall    Reply is bigger than response buffer;
  10713.                                    the buffer will be filled, data will
  10714.                                    be truncated
  10715.  
  10716. FUNCTION ASPGetStatus (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10717.  
  10718. Parameter block
  10719.   -->    26    csCode      word       Always ASPGetStatus
  10720.   -->    30    aspTimeout  byte       Retry interval in seconds
  10721.   -->    31    aspRetry    byte       Number of retries
  10722.   -->    32    serverAddr  long word  Server socket address
  10723.   <->    38    rbSize      word       Reply buffer and reply size
  10724.   -->    40    rbPtr       pointer    Reply buffer pointer
  10725.   -->    50    ccbStart    record     Start of memory for CCB
  10726.  
  10727. ASPGetStatus returns server status.  This call is also used as GetServerInfo at the
  10728. AFP level. This call is unique in that it transfers data over the network without
  10729. having a session open.  This call does not pass any data but requests that server
  10730. status be returned.
  10731.  
  10732. ASPTimeOut is the interval in seconds between retries of the call.
  10733.  
  10734. ASPRetry is the number of retries that will be attempted.
  10735.  
  10736. ServerAddr is the network identifier or address of the socket on which the server is
  10737. listening.
  10738.  
  10739. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  10740. command. RBSize is also returned and indicates the size of the reply that was actually
  10741. returned.
  10742.  
  10743. RBPtr points to the reply buffer.
  10744.  
  10745. CCBStart is the start of the memory to be used by the .XPP driver for the command
  10746. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  10747. the exact requirement refer to the CCB Sizes section of this document.
  10748.  
  10749. Result codes    aspBufTooSmall    Reply is bigger than response buffer,
  10750.                                   or Replysize is bigger than ReplyBuffsize
  10751.                 aspNoServer       No response from server at address used
  10752.                                   in call
  10753.  
  10754. _______________________________________________________________________________
  10755.  
  10756. »AFP Implementation
  10757.  
  10758. The AFPCall function (called AFPCommand in Pascal) passes a command to an AFP server.
  10759.  The first byte of the AFPCall command buffer (the AFP command byte) must contain a
  10760. valid AFP command code.
  10761.  
  10762. Note:  Server information should be gotten through an ASPGetStatus call
  10763.        (described above).  ASPGetStatus is equivalent to the AFPGetSrvrInfo.
  10764.        Making an AFP GetSrvrInfo call using AFPCommand results in an error.
  10765.  
  10766. »Mapping AFP Commands
  10767.  
  10768. Most AFP calls are implemented by XPP through a very simple one-to-one mapping of an
  10769. AFP call to an ASP call without interpretation or verification of the data.
  10770.  
  10771. The .XPP driver maps AFP command codes to ASP commands according to the following
  10772. conventions:
  10773.  
  10774.   AFP Command Code     Comment
  10775.  
  10776.   $00                  Invalid AFP command
  10777.   $01–$BE (1–190)      Mapped to UserCommand  (with the exceptions
  10778.                        listed below)
  10779.   $BF (191)            Mapped to UserCommand  (Reserved for developers;
  10780.                        will never be used by Apple)
  10781.   $C0–$FD (192–253)    Mapped to UserWrite
  10782.   $FE (254)            Mapped to UserWrite  (will never be used by Apple)
  10783.   $FF (255)            Invalid AFP command
  10784.  
  10785. The following AFP calls are exceptions to the above conventions:
  10786.  
  10787.   AFP Command (Code/Decimal)  Comment
  10788.  
  10789.   getSrvrInfo (15)            Mapped to ASPGetStatus  (Use ASPGetStatus
  10790.                               to make this call)
  10791.   login (18)                  Mapped to appropriate log-in dialog including
  10792.                               ASPOpenSession call
  10793.   loginCont (19)              Mapped to appropriate log-in dialog
  10794.   logout (20)                 Mapped to ASPCloseSession
  10795.   write (33)                  Mapped to ASPUserWrite
  10796.  
  10797. The following AFP calls can pass or return more data than can fit in quantumSize
  10798. bytes (eight ATP response packets) and may be broken up by XPP into multiple ASP
  10799. calls.
  10800.  
  10801.   AFP Command (Code/Decimal)  Comment
  10802.  
  10803.   read (27)                   Can return up to the number of bytes
  10804.                               indicated in reqCount
  10805.   write (33)                  Can pass up to the number of bytes
  10806.                               indicated in reqCount
  10807.  
  10808. »AFPCall Function
  10809.  
  10810. The AFPCall function can have one of the following command formats.
  10811.  
  10812.   •  General
  10813.   •  Login
  10814.   •  AFPWrite
  10815.   •  AFPRead
  10816.  
  10817. »General Command Format
  10818.  
  10819. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10820.  
  10821. Parameter block
  10822.   -->    18    cmdResult   long word  AFP command result
  10823.   -->    26    csCode      word       Always AFPCall
  10824.   -->    28    sessRefnum  word       Session reference number
  10825.   -->    30    aspTimeout  byte       Retry interval in seconds
  10826.   -->    32    cbSize      word       Command buffer size
  10827.   -->    34    cbPtr       pointer    Command buffer
  10828.   <->    38    rbSize      word       Reply buffer size and reply size
  10829.   -->    40    rbPtr       pointer    Reply buffer pointer
  10830.   <->    44    wdSize      word       Write data size
  10831.   -->    46    wdPtr       pointer    Write data pointer
  10832.   -->    50    ccbStart    record     Start of memory for CCB
  10833.  
  10834. The general command format for the AFPCall function passes an AFP command to the
  10835. server.  This format is used for all AFP calls except AFPLogin, AFPRead, and AFPWrite.
  10836.   Note that from Pascal this call is referred to as AFPCommand.
  10837.  
  10838. CmdResult is four bytes of data returned from the server containing an indication of
  10839. the result of the AFP command.
  10840.  
  10841. SessRefnum is the session reference number returned in the AFPLogin call.
  10842.  
  10843. ASPTimeOut is the interval in seconds between retries of the call by the driver.
  10844.  
  10845. CBSize is the size in bytes of the block of data that contains the command to be sent
  10846. to the server on the session. The size of the command block must not exceed the value
  10847. of aspMaxCmdSize returned by the ASPGetParms call.
  10848.  
  10849. CBPtr points to start of the block of data (command block) containing the command
  10850. that is to be sent to the server on the session.  The first byte of the command block
  10851. must contain the AFP command byte.  Subsequent bytes in the command buffer contain
  10852. the  parameters associated with the command as defined in the AFP document.
  10853.  
  10854. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  10855. command. RBSize is also returned and indicates the size of the reply that was actually
  10856. returned.
  10857.  
  10858. RBPtr points to the reply buffer.
  10859.  
  10860. WDSize is the size of data to be written to the server (only used if the command is
  10861. one that is mapped to an ASPUserWrite).
  10862.  
  10863. WDPtr points to the write data buffer (only used if the command is one that is mapped
  10864. to an ASPUserWrite).
  10865.  
  10866. CCBStart is the start of the memory to be used by the .XPP driver for the command
  10867. control block.  The size of this block is equal to a maximum of 296 bytes.  To determine
  10868. the exact requirement refer to the CCB Sizes section of this document.
  10869.  
  10870. Result codes    aspParamErr       Invalid session number; session has
  10871.                                   been closed
  10872.                 aspSizeErr        Command block size is bigger than MaxCmdSize
  10873.                 aspSessClosed     Session is closing
  10874.                 aspBufTooSmall    Reply is bigger than response buffer or
  10875.                                   buffer will be filled, data will be truncated
  10876.                 afpParmError      AFP command block size is equal to zero.
  10877.                                   This error will also be returned if the
  10878.                                   command byte in the command block is equal
  10879.                                   to 0 or $FF (255) or GetSrvrStatus (15).
  10880.  
  10881. »Login Command Format
  10882.  
  10883. The AFP login command executes a series of AFP operations as defined in the AFP Draft
  10884. Proposal.  For further information, refer to the AFP document.
  10885.  
  10886. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
  10887.  
  10888. Parameter block
  10889.   -->    18    cmdResult       long word  AFP command result
  10890.   -->    26    csCode          word       Always AFPCall
  10891.   -->    28    sessRefnum      word       Session reference number
  10892.   -->    30    aspTimeout      byte       Retry interval in seconds
  10893.   -->    31    aspRetry        byte       Number of retries
  10894.   -->    32    cbSize          word       Command buffer size
  10895.   -->    34    cbPtr           pointer    Command buffer
  10896.   <->    38    rbSize          word       Reply buffer size and reply size
  10897.   -->    40    rbPtr           pointer    Reply buffer pointer
  10898.   -->    44    afpAddrBlock    long word  Server address block
  10899.   <->    48    afpSCBPtr       pointer    SCB pointer
  10900.   <->    52    afpAttnRoutine  pointer    Attention routine pointer
  10901.   -->    50    ccbStart        record     Start of command control block
  10902.  
  10903. CmdResult is four bytes of data returned from the server containing an indication of
  10904. the result of the AFP command.
  10905.  
  10906. SessRefnum is the session reference number (returned by the AFPLogin call).
  10907.  
  10908. ASPTimeOut is the interval in seconds between retries of the call.
  10909.  
  10910. ASPRetry is the number of retries that will be attempted.
  10911.  
  10912. CBSize is the size in bytes of the block data that contains the command to be sent to
  10913. the server on the session. The size of the command block must not exceed the value of
  10914. aspMaxCmdSize returned by the ASPGetParms call.
  10915.  
  10916. CBPtr points to the block of data (command block) containing the AFP login command
  10917. that is to be sent to the server on the session.  The first byte of the command block
  10918. must be the AFP login command byte.  Subsequent bytes in the command buffer contain
  10919. the parameters associated with the command.
  10920.  
  10921. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  10922. command.  RBSize is also returned and indicates the size of the reply that was actually
  10923. returned.
  10924.  
  10925. RBPtr points to the reply buffer.
  10926.  
  10927. AFPServerAddr is the network identifier or address of the socket on which the server
  10928. is listening.
  10929.  
  10930. AFPSCBPointer points to a locked block of data for the session control block
  10931. (SCB). The SCB size is defined by scbMemSize.  The SCB is a locked block, and as long
  10932. as the session is open, the SCB cannot be modified in any way by the application. 
  10933. There is one SCB for each open session.
  10934.  
  10935. AFPAttnRoutine is a pointer to a routine that is invoked if an attention from the
  10936. server is received.  When afpAttnRoutine is equal to zero, no attention routine will
  10937. be invoked.
  10938.  
  10939. CCBStart is the start of the memory to be used by the .XPP driver for the command
  10940. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  10941. the exact requirement refer to the CCB Sizes section later in this chapter.
  10942.  
  10943. Note:  In the parameter block, the afpSCBPointer and the afpAttnRoutine
  10944.        fields overlap with the start of the CCB and are modified by the call.
  10945.  
  10946. Result codes    aspSizeErr        Command block size is bigger than MaxCmdSize
  10947.                 aspBufTooSmall    Reply is bigger than response buffer or
  10948.                                   buffer will be filled, data will be truncated
  10949.                 aspNoServer       Server not responding
  10950.                 aspServerBusy     Server cannot open another session
  10951.                 aspBadVersNum     Server cannot support the offered ASP
  10952.                                   version number
  10953.                 aspNoMoreSess     Driver cannot support another session.
  10954.  
  10955. »AFPWrite Command Format
  10956.  
  10957. The AFPWrite and AFPRead command formats allow the calling application to make AFP-level
  10958. calls that read or write a data block that is larger than a single ASP-level call is
  10959. capable of reading or writing.  The maximum number of bytes of data that can be read
  10960. or written at the ASP level is equal to quantumSize.
  10961.  
  10962. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10963.  
  10964. Parameter block
  10965.   -->    18    cmdResult   long word  AFP command result
  10966.   -->    26    csCode      word       Always AFPCall
  10967.   -->    28    sessRefnum  word       Session number
  10968.   -->    30    aspTimeout  byte       Retry interval in seconds
  10969.   -->    32    cbSize      word       Command buffer size
  10970.   -->    34    cbPtr       pointer    Command buffer
  10971.   <->    38    rbSize      word       Reply buffer size and reply size
  10972.   -->    40    rbPtr       pointer    Reply buffer pointer
  10973.   -->    44    wdSize      word       (used internally)
  10974.   <->    46    wdPtr       pointer    Write data pointer  (updated)
  10975.   -->    50    ccbStart    record     Start of memory for CCB
  10976.  
  10977. CmdResult is four bytes of data returned from the server containing an indication of
  10978. the result of the AFP command.
  10979.  
  10980. SessRefnum is the session reference number returned in the AFPLogin call.
  10981.  
  10982. ASPTimeOut is the interval in seconds between retries of the call.
  10983.  
  10984. CBSize is the size in bytes of the block data that contains the command to be sent to
  10985. the server on the session.  The size of the command block must not exceed the value
  10986. of aspMaxCmdSize returned by the aspGetParms call.
  10987.  
  10988. CBPtr points to the block of data (see command block structure below) containing the
  10989. AFP write command that is to be sent to the server on the session.  The first byte of
  10990. the Command Block must contain the AFP write command byte.
  10991.  
  10992. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  10993. command.  RBSize is also returned and indicates the size of the reply that was actually
  10994. returned.
  10995.  
  10996. RBPtr points to the reply buffer.
  10997.  
  10998. WDSize is used internally.
  10999.  
  11000. Note:  This command does not pass the write data size in the queue element
  11001.        but in the command buffer.  XPP will look for the size in that buffer.
  11002.  
  11003. WDPtr is a pointer to the block of data to be written.  Note that this field will be
  11004. updated by XPP as it proceeds and will always point to that section of the data which
  11005. XPP is currently writing.
  11006.  
  11007. CCBStart is the start of the memory to be used by the XPP driver for the command
  11008. control block.  The size of this block is equal to a maximum of 296 bytes.  To determine
  11009. the exact requirement refer to the CCB Sizes section later in this chapter.
  11010.  
  11011. Command Block Structure:  The AFP write command passes several arguments to XPP in
  11012. the command buffer itself. The byte offsets are relative to the location pointed to
  11013. by cbPtr.
  11014.  
  11015.   -->    0    cmdByte       byte       AFP call command byte
  11016.   -->    1    startEndFlag  byte       Start/end Flag
  11017.   <->    4    rwOffset      long word  Offset within fork to write
  11018.   <->    8    reqCount      long word  Requested count
  11019.  
  11020. CmdByte is the AFP call command byte and must contain the AFP write command code.
  11021.  
  11022. StartEndFlag is a one-bit flag (the high bit of the byte) indicating whether the
  11023. rwOffset field is relative to the beginning or the end of the fork (all other bits
  11024. are zero).
  11025.  
  11026.   0 = relative to the beginning of the fork
  11027.   1 = relative to the end of the fork
  11028.  
  11029. RWOffset is the byte offset within the fork at which the write is to begin.
  11030.  
  11031. ReqCount indicates the size of the data to be written and is returned as the actual
  11032. size written.
  11033.  
  11034. The rwOffset and reqCount fields are modified by XPP as the write proceeds and will
  11035. always indicate the current value of these fields.
  11036.  
  11037. The Pascal structure of the AFP command buffer follows:
  11038.  
  11039. AFPCommandBlock = PACKED RECORD
  11040.                     cmdByte:       Byte;
  11041.                     startEndFlag:  Byte;
  11042.                     forkRefNum:    INTEGER;    {used by server}
  11043.                     rwOffset:      LONGINT;
  11044.                     reqCount:      LONGINT;
  11045.                     newLineFlag:   Byte;       {unused by write}
  11046.                     newLineChar:   CHAR;       {unused by write}
  11047.                   END;
  11048.  
  11049. Result codes    aspParamErr       Invalid session number
  11050.                 aspSizeErr        Command block size is bigger than MaxCmdSize
  11051.                 aspSessClosed     Session is closing
  11052.                 aspBufTooSmall    Reply is bigger than response buffer
  11053.  
  11054. »AFPRead Command Format
  11055.  
  11056. The AFPWrite and AFPRead command formats allow the calling application to make AFP-level
  11057. calls that read or write a data block that is larger than a single ASP-level call is
  11058. capable of reading or writing.  The maximum number of bytes of data that can be read
  11059. or written at the ASP level is equal to quantumSize.
  11060.  
  11061. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  11062.  
  11063. Parameter block
  11064.   -->    18    cmdResult   long word  ASP command result
  11065.   -->    26    csCode      word       Always AFPCall
  11066.   -->    28    sessRefnum  word       Session number
  11067.   -->    30    aspTimeout  byte       Retry interval in seconds
  11068.   -->    32    cbSize      word       Command buffer size
  11069.   -->    34    cbPtr       pointer    Command buffer
  11070.   -->    38    rbSize      word       Used internally
  11071.   <->    40    rbPtr       pointer    Reply buffer pointer (updated)
  11072.   -->    50    ccbStart    record     Start of memory for CCB
  11073.  
  11074. CmdResult is four bytes of data returned from the server containing an indication of
  11075. the result of the AFP command.
  11076.  
  11077. SessRefnum is the session reference number returned in the AFPLogin  call.
  11078.  
  11079. ASPTimeOut is the interval in seconds between retries of the call.
  11080.  
  11081. CBSize is the size in bytes of the block data that contains the command to be sent to
  11082. the server on the session.  The size of the command block must not exceed the value
  11083. of aspMaxCmdSize returned by the GetParms call.
  11084.  
  11085. CBPtr points to the block of data (command block) containing the AFP read command
  11086. that is to be sent to the server on the session.  The first byte of the command block
  11087. must contain the AFP read command byte.  The command block structure is shown below.
  11088.  
  11089. RBSize  is used internally.
  11090.  
  11091. Note:  This command does not pass the read size in the queue element but
  11092.        in the command buffer.  XPP will look for the size in that buffer.
  11093.  
  11094. RBPtr points to the reply buffer.  Note that this field will be updated by XPP as it
  11095. proceeds and will always point to that section of the buffer that XPP is currently
  11096. reading into.
  11097.  
  11098. CCBStart is the start of the memory to be used by the .XPP driver for the command
  11099. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  11100. the exact requirement refer to The CCB Sizes section later in this chapter.
  11101.  
  11102. Command Block Structure:  The AFP read command passes several arguments to XPP in the
  11103. command buffer itself. The byte offsets are relative to the location pointed to by
  11104. cbPointer.
  11105.  
  11106.   -->    0    cmdByte      byte       AFP call command byte
  11107.   <->    4    rwOffset     long word  Offset within fork to read
  11108.   <->    8    reqCount     long word  Requested count
  11109.   -->    12   newLineFlag  byte       Newline Flag
  11110.   -->    13   newLineChar  byte       Newline Character
  11111.  
  11112. CmdByte is the AFP call command byte and must contain the AFP read command code.
  11113.  
  11114. RWOffset is the byte offset within the fork at which the read is to begin.
  11115.  
  11116. ReqCount  indicates the size of the read data buffer and is returned as the actual
  11117. size read.
  11118.  
  11119. The rwOffset and reqCount fields are modified by XPP as the read proceeds and will
  11120. always indicate the current value of these fields.
  11121.  
  11122. NewLineFlag is a one-bit flag (the high bit of the byte) indicating whether or not
  11123. the read is to terminate at a specified character (all other bits are zero).
  11124.  
  11125.   0 = no Newline Character is specified
  11126.   1 = a Newline Character is specified
  11127.  
  11128. NewLineChar is any character from $00 to $FF (inclusive) that, when encountered in
  11129. reading the fork, causes the read operation to terminate.
  11130.  
  11131. The Pascal structure of the AFPCommand follows:
  11132.  
  11133. AFPCommandBlock = PACKED RECORD
  11134.                     cmdByte:       Byte;
  11135.                     startEndFlag:  Byte;     {unused for read}
  11136.                     forkRefNum:    INTEGER;  {used by server}
  11137.                     rwOffset:      LONGINT;
  11138.                     reqCount:      LONGINT;
  11139.                     newLineFlag:   Byte;
  11140.                     newLineChar:   CHAR;
  11141.                   END;
  11142.  
  11143. Result codes    aspParamErr       Invalid session number
  11144.                 aspSizeErr        Command block size is bigger than MaxCmdSize
  11145.                 aspSessClosed     Session is closing
  11146.                 aspBufTooSmall    Reply is bigger than response buffer
  11147.  
  11148. _______________________________________________________________________________
  11149.  
  11150. »CCB Sizes
  11151.  
  11152. The .XPP driver uses the memory provided at the end of the UserWrite, UserCommand,
  11153. and GetStatus functions parameter blocks as an internal command control block (CCB).
  11154. Using the maximum block sizes specified in the call descriptions will provide adequate
  11155. space for the call to execute successfully. However, this section is provided for
  11156. developers who wish to minimize the amount of memory taken up by the CCB in the queue
  11157. element.
  11158.  
  11159. Specifically, this memory is used for building data structures to be used in making
  11160. calls to the ATP driver.  This includes parameter blocks and buffer data structures
  11161. (BDS). The structure of the BDS is detailed in elsewhere in this chapter.  The exact
  11162. size of this memory depends on the size of the response expected, and, in the case of
  11163. UserWrite, on the size of data to be written.
  11164.  
  11165. In the UserCommand and GetStatus cases (along with all AFP calls which map to UserCommand),
  11166. a BDS must be set up to hold the response information.  The number of entries in this
  11167. BDS is equal to the size of the response buffer divided by the maximum number of data
  11168. bytes per ATP response packet (578), rounded up.  As described in the ASP chapter in
  11169. Inside AppleTalk, ASP must ask for an extra response in the case where the response
  11170. buffer is an exact multiple of 578.  Of course, no BDS can be larger than eight
  11171. elements.  XPP also needs bytes for the queue element to call ATP with, so the minimum
  11172. size of a CCB, as a function of the response buffer size (rbSize) is
  11173.  
  11174.   bdsSize = MIN (((rbSize DIV 578) + 1),8) * bdsEntrySz
  11175.   ccbSize = ioQElSize + 4 + bdsSize
  11176.  
  11177. With UserWrite (and AFP calls mapping to UserWrite), XPP must create an additional
  11178. BDS and queue element to use in sending the write data to the server.  Therefore the 
  11179. minimum size of a UserWrite CCB, as a function of the response buffer and write data
  11180. sizes (rbSize and wdSize) is:
  11181.  
  11182.   wrBDSSize = MIN (((wdSize DIV 578) + 1),8) * bdsEntrySz
  11183.   wrCCBSize = (2 * ioQElSize) + 4 + bdsSize + wrBDSSize
  11184.  
  11185. Note: BDSEntrySz is equal to 12; ioQelSize is equal to 50.
  11186.  
  11187. _______________________________________________________________________________
  11188.  
  11189. ».XPP Driver Result Codes
  11190.  
  11191. Result Code       Comment                                      Returned by
  11192.  
  11193. aspBadVersNum     Server cannot support the offered version    ASPOpenSession
  11194.                   number.                                      AFPCall (Login)
  11195.  
  11196. aspBufTooSmall    Reply is bigger than response buffer.        ASPUserWrite
  11197.                   Buffer will be filled, data may be           ASPUserCommand
  11198.                   truncated.                                   ASPGetStatus
  11199.                                                                AFPCall
  11200.  
  11201. aspNoMoreSess     Driver cannot support another session.       ASPOpenSessION 
  11202.                                                                AFPCall (Login)
  11203.  
  11204. aspNoServers      No servers at that address.                  ASPGetStatus
  11205.                   The server did not respond to the request.   ASPOpenSession
  11206.                                                                AFPCall (Login)
  11207.  
  11208. aspParamErr       Parameter error, server returned bad         ASPOpenSession 
  11209.                   (positive) error code.                       ASPCloseSess
  11210.                   Invalid Session Reference Number.            ASPUserWrite
  11211.                                                                ASPUserCommand
  11212.                                                                AFPCall
  11213.  
  11214. aspServerBusy     Server cannot open another session.          ASPOpenSession
  11215.                                                                AFPCall (Login)
  11216.  
  11217. aspSessClosed     Session already in process of closing.       ASPCloseSession
  11218.                                                                ASPUserWrite
  11219.                                                                ASPUserCommand
  11220.                                                                AFPCall
  11221.  
  11222. aspSizeErr        Command block size is bigger than            ASPUserWrite
  11223.                   maxParamSize.                                ASPUserCommand
  11224.                                                                AFPCall
  11225.  
  11226. cbNotFound        SCB not found, no outstanding                ASPAbortOS
  11227.                   open session to be aborted.  Pointer did
  11228.                   not point to an open session SCB.
  11229.  
  11230. afpParmError      AFP Command Block size is less than or       AFPCall
  11231.                   equal to zero.  Command byte in the
  11232.                   Command block is equal to 0 or $FF (255)
  11233.                   or GetSrvrStatus (15).
  11234.  
  11235. reqAborted        Open session was aborted by an               ASPOpenSession
  11236.                   Abort Open Session.                          AFPCall (Login)
  11237.  
  11238. _______________________________________________________________________________
  11239.  
  11240.  
  11241. æKY Protocol…Handlers…and…Socket…Listeners
  11242. æC »PROTOCOL HANDLERS AND SOCKET LISTENERS                   AppleTalkManager
  11243. _______________________________________________________________________________
  11244.  
  11245. This section describes how to write your own protocol handlers and socket listeners.
  11246. If you’re only interested in using the default protocol handlers and socket listeners
  11247. provided by the Pascal interface, you can skip this section. Protocol handlers and
  11248. socket listeners must be written in assembly language because they’ll be called by
  11249. the .MPP driver with parameters in various registers not directly accessible from
  11250. Pascal.
  11251.  
  11252. The .MPP and .ATP drivers have been designed to maximize overall throughput while
  11253. minimizing code size. Two principal sources of loss of throughput are unnecessary
  11254. buffer copying and inefficient mechanisms for dispatching (routing) packets between
  11255. the various layers of the network protocol architecture. The AppleTalk Manager completely
  11256. eliminates buffer copying by using simple, efficient dispatching mechanisms at two
  11257. important points of the data reception path:  protocol handlers and socket listeners.
  11258. To write your own, you should understand the flow of control in this path.
  11259.  
  11260. _______________________________________________________________________________
  11261.  
  11262. »Data Reception in the AppleTalk Manager
  11263.  
  11264. When the SCC detects an ALAP frame addressed to the particular node (or a broadcast
  11265. frame), it interrupts the Macintosh’s MC68000. An interrupt handler built into the
  11266. .MPP driver gets control and begins servicing the interrupt. Meanwhile, the frame’s
  11267. ALAP header bytes are coming into the SCC’s data reception buffer; this is a three-byte
  11268. FIFO buffer. The interrupt handler must remove these bytes from the SCC’s buffer to
  11269. make room for the bytes right behind; for this purpose, MPP has an internal buffer,
  11270. known as the Read Header Area (RHA), into which it places these three bytes.
  11271.  
  11272. The third byte of the frame contains the ALAP protocol type field. If the most significant
  11273. bit of this field is set (that is, ALAP protocol types 128 to 255), the frame is an
  11274. ALAP control frame. Since ALAP control frames are only three bytes long (plus two CRC
  11275. bytes), for such frames the interrupt handler simply confirms that the CRC bytes
  11276. indicate an error-free frame and then performs the specified action.
  11277.  
  11278. If, however, the frame being received is a data frame (that is, ALAP protocol types 1
  11279. to 127), intended for a higher layer of the protocol architecture implemented on that
  11280. Macintosh, this means that additional data bytes are coming right behind. The interrupt
  11281. handler must immediately pass control to the protocol handler corresponding to the
  11282. protocol type specified in the third byte of the ALAP frame for continued reception
  11283. of the frame. To allow for such a dispatching mechanism, the ALAP code in MPP maintains
  11284. a protocol table. This consists of a list of currently used ALAP protocol types with
  11285. the memory addresses of their corresponding protocol handlers. To allow MPP to transfer
  11286. control to a protocol handler you’ve written, you must make an appropriate entry in
  11287. the protocol table with a valid ALAP protocol type and the memory address of your
  11288. code module.
  11289.  
  11290. To enter your protocol handler into the protocol table, issue the LAPOpenProtocol
  11291. call from Pascal or an AttachPH call from assembly language. Thereafter, whenever an
  11292. ALAP header with your ALAP protocol type is received, MPP will call your protocol
  11293. handler. When you no longer wish to receive packets of that ALAP protocol type, call
  11294. LAPCloseProtocol from Pascal or DetachPH from assembly language.
  11295.  
  11296. Warning:  Remember that ALAP protocol types 1 and 2 are reserved by DDP
  11297.           for the default protocol handler and that types 128 to 255 are
  11298.           used by ALAP for its control frames.
  11299.  
  11300. A protocol handler is a piece of assembly-language code that controls the reception
  11301. of AppleTalk packets of a given ALAP protocol type. More specifically, a protocol
  11302. handler must carry out the reception of the rest of the frame following the ALAP
  11303. header. The nature of a particular protocol handler depends on the characteristics of
  11304. the protocol for which it was written. In the simplest case, the protocol handler
  11305. simply reads the entire packet into an internal buffer. A more sophisticated protocol
  11306. handler might read in the header of its protocol, and on the basis of information
  11307. contained in it, decide where to put the rest of the packet’s data. In certain cases,
  11308. the protocol handler might, after examining the header corresponding to its own
  11309. protocol, in turn transfer control to a similar piece of code at the next-higher
  11310. level of the protocol architecture (for example, in the case of DDP, its protocol
  11311. handler must call the socket listener of the datagram’s destination socket).
  11312.  
  11313. In this way, protocol handlers are used to allow “on the fly” decisions regarding the
  11314. intended recipient of the packets’s data, and thus avoid buffer copying. By using
  11315. protocol handlers and their counterparts in higher layers
  11316. (for instance, socket listeners), data sent over the AppleTalk network is read directly
  11317. from the network into the destination’s buffer.
  11318.  
  11319. _______________________________________________________________________________
  11320.  
  11321. »Writing Protocol Handlers
  11322.  
  11323. When the .MPP driver calls your protocol handler, it has already read the first five
  11324. bytes of the packet into the RHA. These are the three-byte ALAP header and the next
  11325. two bytes of the packet. The two bytes following the header must contain the length
  11326. in bytes of the data in the packet, including these two bytes themselves, but excluding
  11327. the ALAP header.
  11328.  
  11329. Note:  Since ALAP packets can have at most 600 data bytes, only the lower
  11330.        ten bits of this length value are significant.
  11331.  
  11332. After determining how many bytes to read and where to put them, the protocol handler
  11333. must call one or both of two functions that perform all the low-level manipulation of
  11334. the SCC required to read bytes from the network. ReadPacket can be called repeatedly
  11335. to read in the packet piecemeal or ReadRest can be called to read the rest of the
  11336. packet. Any number of ReadPacket calls can be used, as long as a ReadRest call is
  11337. made to read the final piece of the packet. This is necessary because ReadRest restores
  11338. state information and verifies that the hardware-generated CRC is correct. An error
  11339. will be returned if the protocol handler attempts to use ReadPacket to read more
  11340. bytes than remain in the packet.
  11341.  
  11342. When MPP passes control to your protocol handler, it passes various parameters and
  11343. pointers in the processor’s registers:
  11344.  
  11345.   Register(s)    Contents
  11346.  
  11347.   A0-A1          SCC addresses used by MPP
  11348.   A2             Pointer to MPP’s local variables (discussed below)
  11349.   A3             Pointer to next free byte in RHA
  11350.   A4             Pointer to ReadPacket and ReadRest jump table
  11351.   D1 (word)      Number of bytes left to read in packet
  11352.  
  11353. These registers, with the exception of A3, must be preserved until ReadRest is called.
  11354. A3 is used as an input parameter to ReadPacket and ReadRest, so its contents may be
  11355. changed. D0, D2, and D3 are free for your use. In addition, register A5 has been
  11356. saved by MPP and may be used by the protocol handler until ReadRest is called. When
  11357. control returns to the protocol handler from ReadRest, MPP no longer needs the data
  11358. in these registers. At that point, standard interrupt routine conventions apply and
  11359. the protocol handler can freely use
  11360. A0-A3 and D0-D3 (they’re restored by the interrupt handler).
  11361.  
  11362. D1 contains the number of bytes left to be read in the packet as derived from the
  11363. packet’s length field. A transmission error could corrupt the length field or some
  11364. bytes in the packet might be lost, but this won’t be discovered until the end of the
  11365. packet is reached and the CRC checked.
  11366.  
  11367. When the protocol handler is first called, the first five bytes of the packet
  11368. (ALAP destination node ID, source node ID, ALAP protocol type, and length) can be
  11369. read from the RHA. Since A3 is pointing to the next free position in the RHA, these
  11370. bytes can be read using negative offsets from A3. For instance, the ALAP source node
  11371. ID is at –4(A3), the packet’s data length (given in D1) is also pointed to by –2(A3),
  11372. and so on. Alternatively, they can be accessed as positive offsets from the top of
  11373. the RHA. The effective address of the top of the RHA is toRHA(A2), so the following
  11374. code could be used to obtain the ALAP type field:
  11375.  
  11376.   LEA       toRHA(A2),A5      ;A5 points to top of RHA
  11377.   MOVE.B    lapType(A5),D2    ;load D2 with type field
  11378.  
  11379. These methods are valid only as long as SCC interrupts remain locked out (which they
  11380. are when the protocol handler is first called). If the protocol handler lowers the
  11381. interrupt level, another packet could arrive over the network and invalidate the
  11382. contents of the RHA.
  11383.  
  11384. •••Refer to Technical Note #201:•••
  11385.  
  11386. You can call ReadPacket by jumping through the jump table in the following way:
  11387.  
  11388.   JSR (A4)
  11389.  
  11390.   On entry    D3:    number of bytes to be read (word)
  11391.               A3:    pointer to a buffer to hold the bytes
  11392.   On exit     D0:    modified
  11393.               D1:    number of bytes left to read in packet (word)
  11394.               D2:    preserved
  11395.               D3:    =  0 if requested number of bytes were read
  11396.                      <> 0 if error
  11397.               A0-A2: preserved
  11398.               A3:    pointer to one byte past the last byte read
  11399.  
  11400. ReadPacket reads the number of bytes specified in D3 into the buffer pointed to by
  11401. A3. The number of bytes remaining to be read in the packet is returned in D1. A3
  11402. points to the byte following the last byte read.
  11403.  
  11404. You can call ReadRest by jumping through the jump table in the following way:
  11405.  
  11406.   JSR 2(A4)
  11407.  
  11408.   On entry    A3:    pointer to a buffer to hold the bytes
  11409.               D3:    size of the buffer (word)
  11410.   On exit     D0-D1: modified
  11411.               D2:    preserved
  11412.               D3:    = 0 if packet was exactly the size of the buffer
  11413.                      < 0 if packet was (–D3) bytes too large to fit in
  11414.                          buffer and was truncated
  11415.                      > 0 if D3 bytes weren't read (packet is smaller
  11416.                          than buffer)
  11417.               A0-A2: preserved
  11418.               A3:    pointer to one byte past the last byte read
  11419.  
  11420. ReadRest reads the remaining bytes of the packet into the buffer whose size is given
  11421. in D3 and whose location is pointed to by A3. The result of the operation is returned
  11422. in D3.
  11423.  
  11424. ReadRest can be called with D3 set to a buffer size greater than the packet size;
  11425. ReadPacket cannot (it will return an error).
  11426.  
  11427. Warning:  Remember to always call ReadRest to read the last part of a
  11428.           packet; otherwise the system will eventually crash.
  11429.  
  11430. If at any point before it has read the last byte of a packet, the protocol handler
  11431. wants to discard the remaining data, it should terminate by calling ReadRest as
  11432. follows:
  11433.  
  11434.   MOVEQ    #0,D3    ;byte count of 0
  11435.   JSR      2(A4)    ;call ReadRest
  11436.   RTS
  11437.  
  11438. Or, equivalently:
  11439.  
  11440.   MOVEQ    #0,D3    ;byte count of 0
  11441.   JMP      2(A4)    ;JMP to ReadRest, not JSR
  11442.  
  11443. In all other cases, the protocol handler should end with an RTS, even if errors were
  11444. detected. If MPP returns an error from a ReadPacket call, the protocol handler must
  11445. quit via an RTS without calling ReadRest at all (in this case it has already been
  11446. called by MPP).
  11447.  
  11448. The Z (Zero) condition code is set upon return from these routines to indicate the
  11449. presence of errors (CRC, overrun, and so on). Zero bit set means no error was detected;
  11450. a nonzero condition code implies an error of some kind.
  11451.  
  11452. Up to 24 bytes of temporary storage are available in MPP’s RHA. When the protocol
  11453. handler is called, 19 of these bytes are free for its use. It may read several bytes
  11454. (at least four are suggested) into this area to empty the SCC’s buffer and buy some
  11455. time for further processing.
  11456.  
  11457. MPP’s globals include some variables that you may find useful. They’re allocated as a
  11458. block of memory pointed to by the contents of the global variable ABusVars, but a
  11459. protocol handler can access them by offsets from A2:
  11460.  
  11461.   Name          Contents
  11462.  
  11463.   sysLAPAddr    This node’s node ID (byte)
  11464.   toRHA         Top of the Read Header Area (24 bytes)
  11465.   sysABridge    Node ID of a bridge (byte)
  11466.   sysNetNum     This node’s network number (word)
  11467.   vSCCEnable    Status Register (SR) value to re-enable SCC interrupts (word)
  11468.  
  11469. Warning:  Under no circumstances should your protocol handler modify
  11470.           these variables. It can read them to find the node’s ID, its
  11471.           network number, and the node ID of a bridge on the AppleTalk internet.
  11472.  
  11473. If, after reading the entire packet from the network and using the data in the RHA,
  11474. the protocol handler needs to do extensive post-processing, it can load the value in
  11475. vSCCEnable into the SR to enable interrupts. To allow your programs to run transparently
  11476. on any Macintosh, use the value in vSCCEnable rather than directly manipulating the
  11477. interrupt level by changing specific bits in the SR.
  11478.  
  11479. Additional information, such as the driver’s version number or reference number and a
  11480. pointer (or handle) to the driver itself, may be obtained from MPP’s device control
  11481. entry. This can be found by dereferencing the handle in the unit table’s entry corresponding
  11482. to unit number 9; for more information, see the section “The Structure of a Device
  11483. Driver” in the Device Manager chapter.
  11484.  
  11485. »Timing Considerations
  11486.  
  11487. Once it’s been called by MPP, your protocol handler has complete responsibility for
  11488. receiving the rest of the packet. The operation of your protocol handler is time-critical.
  11489. Since it’s called just after MPP has emptied the SCC’s three-byte buffer, the protocol
  11490. handler has approximately 95 microseconds (best case) before it must call ReadPacket
  11491. or ReadRest. Failure to do so will result in an overrun of the SCC’s buffer and loss
  11492. of packet information. If, within that time, the protocol handler can’t determine
  11493. where to put the entire incoming packet, it should call ReadPacket to read at least
  11494. four bytes into some private buffer (possibly the RHA). Doing this will again empty
  11495. the SCC’s buffer and buy another 95 microseconds. You can do this as often as necessary,
  11496. as long as the processing time between successive calls to ReadPacket doesn’t exceed
  11497. 95 microseconds.
  11498.  
  11499. _______________________________________________________________________________
  11500.  
  11501. »Writing Socket Listeners
  11502.  
  11503. A socket listener is a piece of assembly-language code that receives datagrams delivered
  11504. by the DDP built-in protocol handler and delivers them to the client owning that
  11505. socket.
  11506.  
  11507. When a datagram (a packet with ALAP protocol type 1 or 2) is received by the ALAP,
  11508. DDP’s built-in protocol handler is called. This handler reads the DDP header into the
  11509. RHA, examines the destination socket number, and determines whether this socket is
  11510. open by searching DDP’s socket table. This table lists the socket number and corresponding
  11511. socket listener address for each open socket. If an entry is found matching the
  11512. destination socket, the protocol handler immediately transfers control to the appropriate
  11513. socket listener. (To allow DDP to recognize and branch to a socket listener you’ve
  11514. written, call DDPOpenSocket from Pascal or OpenSkt from assembly language.)
  11515.  
  11516. At this point, the registers are set up as follows:
  11517.  
  11518.   Register(s)    Contents
  11519.  
  11520.   A0-A1          SCC addresses used by MPP
  11521.   A2             Pointer to MPP’s local variables (discussed above)
  11522.   A3             Pointer to next free byte in RHA
  11523.   A4             Pointer to ReadPacket and ReadRest jump table
  11524.   D0             This packet’s destination socket number (byte)
  11525.   D1             Number of bytes left to read in packet (word)
  11526.  
  11527. The entire ALAP and DDP headers are in the RHA; these are the only bytes of the
  11528. packet that have been read in from the SCC’s buffer. The socket listener can get the
  11529. destination socket number from D0 to select a buffer into which the packet can be
  11530. read. The listener then calls ReadPacket and ReadRest as described under “Writing
  11531. Protocol Handlers” above. The timing considerations discussed in that section apply
  11532. as well, as do the issues related to accessing the MPP local variables.
  11533.  
  11534. The socket listener may examine the ALAP and DDP headers to extract the various
  11535. fields relevant to its particular client’s needs. To do so, it must first examine the
  11536. ALAP protocol type field (three bytes from the beginning of the RHA) to decide whether
  11537. a short (ALAP protocol type=1) or long (ALAP protocol type=2) header has been received.
  11538.  
  11539. A long DDP header containing a nonzero checksum field implies that the datagram was
  11540. checksummed at the source. In this case, the listener can recalculate the checksum
  11541. using the received datagram, and compare it with the checksum value. The following
  11542. subroutine can be used for this purpose:
  11543.  
  11544.   DoChksum    ;
  11545.               ; D1 (word) = number of bytes to checksum
  11546.               ; D3 (word) = current checksum
  11547.               ; A1 points to the bytes to checksum
  11548.               ;
  11549.               CLR.W     D0          ;clear high byte
  11550.               SUBQ.W    #1,D1       ;decrement count for DBRA
  11551.   Loop        MOVE.B    (A1)+,D0    ;read a byte into D0
  11552.               ADD.W     D0,D3       ;accumulate checksum
  11553.               ROL.W     #1,D3       ;rotate left one bit
  11554.               DBRA      D1,Loop     ;loop if more bytes
  11555.               RTS
  11556.  
  11557. Note:  D0 is modified by DoChksum.
  11558.  
  11559. The checksum must be computed for all bytes starting with the DDP header byte following
  11560. the checksum field up to the last data byte (not including the CRC bytes). The socket
  11561. listener must start by first computing the checksum for the DDP header fields in the
  11562. RHA. This is done as follows:
  11563.  
  11564.               CLR.W     D3          ;set checksum to 0
  11565.               MOVEQ     #ddpHSzLong-ddpDstNet,D1
  11566.                                     ;length of header part to checksum
  11567.               LEA       toRHA+lapHdSz+ddpDstNet(A2),A1
  11568.                                     ;point to destination network number
  11569.               JSR       DoChksum
  11570.               ; D3 = accumulated checksum of DDP header part
  11571.  
  11572. The socket listener must now continue to set up D1 and A1 for each subsequent portion
  11573. of the datagram, and call DoChksum for each. It must not alter the value in D3.
  11574.  
  11575. The situation of the calculated checksum being equal to 0 requires special attention.
  11576. For such packets, the source sends a value of –1 to distinguish them from unchecksummed
  11577. packets. At the end of its checksum computation, the socket listener must examine the
  11578. value in D3 to see if it’s 0. If so, it’s converted to –1 and compared with the
  11579. received checksum to determine whether there was a checksum error:
  11580.  
  11581.               TST.W     D3          ;is calculated value 0?
  11582.               BNE.S     @1          ;no -- go and use it
  11583.               SUBQ.W    #1,D3       ;it is 0; make it -1
  11584.   @1          CMP.W     toRHA+lapHdSz+ddpChecksum(A2),D3
  11585.               BNE       ChksumError
  11586.  
  11587. _______________________________________________________________________________
  11588.  
  11589.  
  11590. æKY Summary…of…the…AppleTalk…Manager
  11591. æC »SUMMARY OF THE APPLETALK MANAGER                         AppleTalkManager
  11592. _______________________________________________________________________________
  11593.  
  11594. Constants
  11595.  
  11596. CONST
  11597.   lapSize = 20;   {ABusRecord size for ALAP}
  11598.   ddpSize = 26;   {ABusRecord size for DDP}
  11599.   nbpSize = 26;   {ABusRecord size for NBP}
  11600.   atpSize = 56;   {ABusRecord size for ATP}
  11601.  
  11602. _______________________________________________________________________________
  11603.  
  11604. Data Types
  11605.  
  11606. TYPE
  11607.   ABProtoType = (lapProto,ddpProto,nbpProto,atpProto);
  11608.   ABRecHandle = ^ABRecPtr;
  11609.   ABRecPtr    = ^ABusRecord;
  11610.   ABusRecord  =
  11611.     RECORD
  11612.        abOpcode:        ABCallType;    {type of call}
  11613.        abResult:        INTEGER;       {result code}
  11614.        abUserReference: LONGINT;       {for your use}
  11615.        CASE ABProtoType OF
  11616.          lapProto:
  11617.           (lapAddress:  LAPAdrBlock; {destination or source node ID}
  11618.            lapReqCount: INTEGER;     {length of frame data or buffer size in }
  11619.                                      { bytes}
  11620.            lapActCount  INTEGER;     {number of frame data bytes actually }
  11621.                                      { received}
  11622.            lapDataPtr:  Ptr);        {pointer to frame data or pointer to }
  11623.                                      { buffer}
  11624.          ddpProto:
  11625.           (ddpType:     Byte;        {DDP protocol type}
  11626.            ddpSocket:   Byte;        {source or listening socket number}
  11627.            ddpAddress:  AddrBlock;   {destination or source socket address}
  11628.            ddpReqCount: INTEGER;     {length of datagram data or buffer size }
  11629.                                      { in bytes}
  11630.            ddpActCount: INTEGER;     {number of bytes actually received}
  11631.            ddpDataPtr:  Ptr;         {pointer to buffer}
  11632.            ddpNodeID:   Byte);       {original destination node ID}
  11633.          nbpProto:
  11634.           (nbpEntityPtr:     EntityPtr;    {pointer to entity name}
  11635.            nbpBufPtr:        Ptr;          {pointer to buffer}
  11636.            nbpBufSize:       INTEGER;      {buffer size in bytes}
  11637.            nbpDataField:     INTEGER;      {number of addresses or socket }
  11638.                                            { number}
  11639.            nbpAddress:       AddrBlock;    {socket address}
  11640.            nbpRetransmitInfo:RetransType); {retransmission information}
  11641.         atpProto:
  11642.          (atpSocket:     Byte;       {listening or responding socket number}
  11643.           atpAddress:    AddrBlock;  {destination or source socket address}
  11644.           atpReqCount:   INTEGER;    {request size or buffer size}
  11645.           atpDataPtr     Ptr;        {pointer to buffer}
  11646.           atpRspBDSPtr:  BDSPtr;     {pointer to response BDS}
  11647.           atpBitMap:     BitMapType; {transaction bit map}
  11648.           atpTransID:    INTEGER;    {transaction ID}
  11649.           atpActCount:   INTEGER;    {number of bytes actually received}
  11650.           atpUserData:   LONGINT;    {user bytes}
  11651.           atpXO:         BOOLEAN;    {exactly-once flag}
  11652.           atpEOM:        BOOLEAN;    {end-of-message flag}
  11653.           atpTimeOut:    Byte;       {retry timeout interval in seconds}
  11654.           atpRetries:    Byte;       {maximum number of retries}
  11655.           atpNumBufs:    Byte;       {number of elements in response BDS or }
  11656.                                      { number of response packets sent}
  11657.           atpNumRsp:     Byte;       {number of response packets received or }
  11658.                                      { sequence number}
  11659.           atpBDSSize:    Byte;       {number of elements in response BDS}
  11660.           atpRspUData:   LONGINT;    {user bytes sent or received in }
  11661.                                      { transaction response}
  11662.           atpRspBuf:     Ptr;        {pointer to response message buffer}
  11663.           atpRspSize:    INTEGER);   {size of response message buffer}
  11664.     END;
  11665.  
  11666.   ABCallType = (tLAPRead,tLAPWrite,tDDPRead,tDDPWrite,tNBPLookup,tNBPConfirm,
  11667.                 tNBPRegister,tATPSndRequest,tATPGetRequest,tATPSdRsp,tATPAddRsp,
  11668.                 tATPRequest,tATPResponse);
  11669.  
  11670.   LAPAdrBlock = PACKED RECORD
  11671.                   dstNodeID:    Byte;   {destination node ID}
  11672.                   srcNodeID:    Byte;   {source node ID}
  11673.                   lapProtType:  ABByte  {ALAP protocol type}
  11674.                 END;
  11675.  
  11676.   ABByte = 1..127; {ALAP protocol type}
  11677.   AddrBlock = PACKED RECORD
  11678.                 aNet:     INTEGER;  {network number}
  11679.                 aNode:    Byte;     {node ID}
  11680.                 aSocket:  Byte      {socket number}
  11681.               END;
  11682.  
  11683.   BDSPtr     = ^BDSType;
  11684.   BDSType    = ARRAY[0..7] OF BDSElement; {response BDS}
  11685.   BDSElement = RECORD
  11686.                  buffSize:   INTEGER;  {buffer size in bytes}
  11687.                  buffPtr:    Ptr;      {pointer to buffer}
  11688.                  dataSize:   INTEGER;  {number of bytes actually received}
  11689.                  userBytes:  LONGINT   {user bytes}
  11690.                END;
  11691.  
  11692.   BitMapType = PACKED ARRAY[0..7] OF BOOLEAN;
  11693.   EntityPtr  = ^EntityName;
  11694.   EntityName = RECORD
  11695.                  objStr:   Str32;  {object}
  11696.                  typeStr:  Str32;  {type}
  11697.                  zoneStr:  Str32    {zone}
  11698.                END;
  11699.  
  11700.   Str32 = STRING[32];
  11701.   RetransType =
  11702.       PACKED RECORD
  11703.         retransInterval:  Byte;  {retransmit interval in 8-tick units}
  11704.         retransCount:     Byte   {total number of attempts}
  11705.       END;
  11706.  
  11707.   MPPParamBlock = PACKED RECORD
  11708.        qLink:          QElemPtr;     {next queue entry}
  11709.        qType:          INTEGER;      {queue type}
  11710.        ioTrap:         INTEGER;      {routine trap}
  11711.        ioCmdAddr:      Ptr;          {routine address}
  11712.        ioCompletion:   ProcPtr;      {completion routine}
  11713.        ioResult:       OSErr;        {result code}
  11714.        ioNamePtr:      StringPtr;    {command result (ATP user bytes) [long]}
  11715.        ioVRefNum:      INTEGER;      {volume reference or drive number}
  11716.        ioRefNum:       INTEGER;      {driver reference number}
  11717.        csCode:         INTEGER;      {call command code AUTOMATICALLY SET}
  11718.  
  11719.        CASE MPPParmType OF
  11720.        LAPWriteParm:
  11721.                     (filler0:INTEGER;
  11722.                     wdsPointer:Ptr);    {->Write Data Structure}
  11723.        AttachPHParm,DetachPHParm:
  11724.                     (protType:Byte;     {ALAP Protocol Type}
  11725.                     filler1:Byte;
  11726.                     handler:Ptr);       {->protocol handler routine}
  11727.        OpenSktParm,CloseSktParm,WriteDDPParm:
  11728.                     (socket:Byte;       {socket number}
  11729.                     checksumFlag:Byte;  {checksum flag}
  11730.                     listener:Ptr);      {->socket listener routine}
  11731.        RegisterNameParm,LookupNameParm,ConfirmNameParm,RemoveNameParm:
  11732.                     (interval:Byte;     {retry interval}
  11733.                     count:Byte;         {retry count}
  11734.                     entityPtr:Ptr;      {->names table element or }
  11735.                                         { ->entity name}
  11736.                     CASE MPPParmType OF
  11737.                     RegisterNameParm:
  11738.                              (verifyFlag:Byte;     {set if verify needed}
  11739.                               filler3:Byte);
  11740.                     LookupNameParm:
  11741.                                     (retBuffPtr:Ptr;       {->return buffer}
  11742.                                     retBuffSize:INTEGER;   {return buffer size}
  11743.                                     maxToGet:INTEGER;      {matches to get}
  11744.                                     numGotten:INTEGER);    {matched gotten}
  11745.                     ConfirmNameParm:
  11746.                                     (confirmAddr:AddrBlock; {->entity}
  11747.                                     newSocket:Byte;         {socket number}
  11748.                                     filler4:Byte));
  11749.  
  11750.        SetSelfSendParm:
  11751.                     (newSelfFlag:Byte;  {self-send toggle flag}
  11752.                     oldSelfFlag:Byte);  {previous self-send state}
  11753.        KillNBPParm:
  11754.                     (nKillQEl:Ptr);     {ptr to Q element to cancel}
  11755.      END;
  11756.  
  11757. ATPParamBlock = PACKED RECORD
  11758.          qLink:            QElemPtr;    {next queue entry}
  11759.          qType:            INTEGER;     {queue type}
  11760.          ioTrap:           INTEGER;     {routine trap}
  11761.          ioCmdAddr:        Ptr;         {routine address}
  11762.          ioCompletion:     ProcPtr;     {completion routine}
  11763.          ioResult:         OSErr;       {result code}
  11764.          userData:         LONGINT;     {ATP user bytes [long]}
  11765.          reqTID:           INTEGER;     {request transaction ID}
  11766.          ioRefNum:         INTEGER;     {driver reference number
  11767.          csCode:           INTEGER;     {Call command code }
  11768.                                         { AUTOMATICALLY SET}
  11769.          atpSocket:        Byte;        {currBitMap or socket number}
  11770.          atpFlags:         Byte;        {control information}
  11771.          addrBlock:        AddrBlock;   {source/dest. socket address}
  11772.          reqLength:        INTEGER;     {request/response length}
  11773.          reqPointer:       Ptr;         {-> request/response data}
  11774.          bdsPointer:       Ptr;         {-> response BDS}
  11775.          CASE MPPParmType OF
  11776.                 SendRequestParm,NSendRequestParm:
  11777.                     (numOfBuffs:Byte;   {numOfBuffs}
  11778.                     timeOutVal:Byte;    {timeout interval}
  11779.                     numOfResps:Byte;    {number responses actually received}
  11780.                     retryCount:Byte;    {number of retries}
  11781.                     intBuff:INTEGER);   {used internally for NSendRequest}
  11782.                 SendResponseParm:
  11783.                     (filler0:Byte;      {number of responses being sent}
  11784.                     bdsSize:Byte;       {number of BDS elements}
  11785.                     transID:INTEGER);   {transaction ID}
  11786.                 GetRequestParm:
  11787.                     (bitMap:Byte;       {bit map}
  11788.                     filler1:Byte);
  11789.                 AddResponseParm:
  11790.                     (rspNum:Byte;       {sequence number}
  11791.                     filler2:Byte);
  11792.                 KillSendReqParm,KillGetReqParm:
  11793.                     (aKillQEl:Ptr);     {ptr to Q element to cancel}
  11794.          END;
  11795.  
  11796.   XPPParamBlock = PACKED RECORD
  11797.     qLink:         QElemPtr;  {next queue entry}
  11798.     qType:         INTEGER;   {queue type}
  11799.     ioTrap:        INTEGER;   {routine trap}
  11800.     ioCmdAddr:     Ptr;       {routine address}
  11801.     ioCompletion:  ProcPtr;   {completion routine}
  11802.     ioResult:      OSErr;     {result code}
  11803.     cmdResult:     LONGINT;   {command result (ATP user bytes) [long]}
  11804.     ioVRefNum:     INTEGER;   {volume reference or drive number)
  11805.     ioRefNum:      INTEGER;   {driver reference number)
  11806.     csCode:        INTEGER;   {Call command code}
  11807.     CASE XPPPrmBlkType OF
  11808.       ASPAbortPrm:
  11809.         (abortSCBPtr:    Ptr);      {SCB pointer for AbortOS [long]}
  11810.       ASPSizeBlk:
  11811.         (aspMaxCmdSize:  INTEGER;   {for SPGetParms [word]
  11812.         aspQuantumSize:  INTEGER;   {for SPGetParms [word]}
  11813.         numSesss:        INTEGER);  {for SPGetParms [word]}
  11814.       XPPPrmBlk:
  11815.         (sessRefnum:     INTEGER;   {offset to session refnum [word]}
  11816.         aspTimeout:      Byte;      {timeout for ATP [byte]}
  11817.         aspRetry:        Byte;      {retry count for ATP [byte]}
  11818.         CASE XPPSubPrmType OF
  11819.           ASPOpenPrm:
  11820.             (serverAddr:    AddrBlock;  {server address block [longword]}
  11821.             scbPointer:     Ptr;        {SCB pointer [longword]}
  11822.             attnRoutine:    Ptr);       {attention routine pointer [long]}
  11823.           ASPSubPrm:
  11824.             (cbSize:        INTEGER;    {command block size [word]}
  11825.             cbPtr:          Ptr;        {command block pointer [long]}
  11826.             rbSize:         INTEGER;    {reply buffer size [word]}
  11827.             rbPtr:          Ptr;        {reply buffer pointer [long]}
  11828.             CASE XPPEndPrmType OF
  11829.               AFPLoginPrm:
  11830.                 (afpAddrBlock:     AddrBlock;    {address block in}
  11831.                                                  { AFPlogin [long]}
  11832.                 afpSCBPtr:         Ptr;          {SCB pointer in }
  11833.                                                  { AFPlogin [long]}
  11834.                 afpAttnRoutine:    Ptr);         {attn routine pointer }
  11835.                                                  { in AFPlogin}
  11836.               ASPEndPrm:
  11837.                 (wdSize:           INTEGER;      {write data size [word]}
  11838.                 wdPtr:             Ptr;          {write data pointer [long]}
  11839.                 ccbStart:          ARRAY[0..295] OF Byte)));   {CCB memory }
  11840.                                                                { for driver}
  11841.      {Write max size(CCB) = 296; all other calls = 150}
  11842.      END;
  11843.  
  11844. AFPCommandBlock = PACKED RECORD
  11845.                     cmdByte:       Byte;
  11846.                     startEndFlag:  Byte;
  11847.                     forkRefNum:    INTEGER;    {used by server}
  11848.                     rwOffset:      LONGINT;
  11849.                     reqCount:      LONGINT;
  11850.                     newLineFlag:   Byte;       {unused by write}
  11851.                     newLineChar:   CHAR;       {unused by write}
  11852.                   END;
  11853.  
  11854. AFPCommandBlock = PACKED RECORD
  11855.                     cmdByte:       Byte;
  11856.                     startEndFlag:  Byte;     {unused for read}
  11857.                     forkRefNum:    INTEGER;  {used by server}
  11858.                     rwOffset:      LONGINT;
  11859.                     reqCount:      LONGINT;
  11860.                     newLineFlag:   Byte;
  11861.                     newLineChar:   CHAR;
  11862.                   END;
  11863.  
  11864. _______________________________________________________________________________
  11865.  
  11866. Routines
  11867.  
  11868. Opening and Closing AppleTalk
  11869.  
  11870. FUNCTION MPPOpen :  OSErr;
  11871. FUNCTION MPPClose : OSErr;
  11872.  
  11873. AppleTalk Link Access Protocol
  11874.  
  11875. FUNCTION LAPOpenProtocol  (theLAPType: ABByte; protoPtr: Ptr) : OSErr;
  11876. FUNCTION LAPCloseProtocol (theLAPType: ABByte) : OSErr;
  11877.  
  11878. FUNCTION LAPWrite (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  11879.   <--    abOpcode                {always tLAPWrite}
  11880.   <--    abResult                {result code}
  11881.   -->    abUserReference         {for your use}
  11882.   -->    lapAddress.dstNodeID    {destination node ID}
  11883.   -->    lapAddress.lapProtType  {ALAP protocol type}
  11884.   -->    lapReqCount             {length of frame data}
  11885.   -->    lapDataPtr              {pointer to frame data}
  11886.  
  11887. FUNCTION LAPRead (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  11888.   <--    abOpcode                {always tLAPRead}
  11889.   <--    abResult                {result code}
  11890.   -->    abUserReference         {for your use}
  11891.   <--    lapAddress.dstNodeID    {destination node ID}
  11892.   <--    lapAddress.srcNodeID    {source node ID}
  11893.   -->    lapAddress.lapProtType  {ALAP protocol type}
  11894.   -->    lapReqCount             {buffer size in bytes}
  11895.   <--    lapActCount             {number of frame data bytes actually received}
  11896.   -->    lapDataPtr              {pointer to buffer}
  11897.  
  11898. FUNCTION LAPRdCancel (abRecord: ABRecHandle) : OSErr;
  11899.  
  11900. Datagram Delivery Protocol
  11901.  
  11902. FUNCTION DDPOpenSocket  (VAR theSocket: Byte; sktListener: Ptr) : OSErr;
  11903. FUNCTION DDPCloseSocket (theSocket: Byte) : OSErr;
  11904.  
  11905. FUNCTION DDPWrite (abRecord: ABRecHandle; doChecksum: BOOLEAN;
  11906.                    async:  BOOLEAN) : OSErr;
  11907.   <--    abOpcode         {always tDDPWrite}
  11908.   <--    abResult         {result code}
  11909.   -->    abUserReference  {for your use}
  11910.   -->    ddpType          {DDP protocol type}
  11911.   -->    ddpSocket        {source socket number}
  11912.   -->    ddpAddress       {destination socket address}
  11913.   -->    ddpReqCount      {length of datagram data}
  11914.   -->    ddpDataPtr       {pointer to buffer}
  11915.  
  11916. FUNCTION DDPRead (abRecord: ABRecHandle; retCksumErrs: BOOLEAN;
  11917.                   async: BOOLEAN) : OSErr;
  11918.   <--    abOpcode         {always tDDPRead}
  11919.   <--    abResult         {result code}
  11920.   -->    abUserReference  {for your use}
  11921.   <--    ddpType          {DDP protocol type}
  11922.   -->    ddpSocket        {listening socket number}
  11923.   <--    ddpAddress       {source socket address}
  11924.   -->    ddpReqCount      {buffer size in bytes}
  11925.   <--    ddpActCount      {number of bytes actually received}
  11926.   -->    ddpDataPtr       {pointer to buffer}
  11927.   <--    ddpNodeID        {original destination node ID}
  11928.  
  11929. FUNCTION DDPRdCancel (abRecord: ABRecHandle) : OSErr;
  11930.  
  11931. AppleTalk Transaction Protocol
  11932.  
  11933. FUNCTION PNSendRequest (thePBptr: ATPBPtr; async: BOOLEAN) : OSErr;
  11934.   -->    18    userData     longword  User bytes
  11935.   <--    22    reqTID       word      Transaction ID used in request
  11936.   -->    26    csCode       word      Always sendRequest
  11937.   <->    28    atpSocket    byte      Socket to send request on
  11938.                                        or Current bitmap
  11939.   <->    29    atpFlags     byte      Control information
  11940.   -->    30    addrBlock    longword  Destination socket address
  11941.   -->    34    reqLength    word      Dequest size in bytes
  11942.   -->    36    reqPointer   pointer   Pointer to request data
  11943.   -->    40    bdsPointer   pointer   Pointer to response BDS
  11944.   -->    44    numOfBuffs   byte      Number of responses expected
  11945.   -->    45    timeOutVal   byte      Timeout interval
  11946.   <--    46    numOf Resps  byte      Number of responses received
  11947.   <->    47    retryCount   byte      Number of retries
  11948.   <--    48    intBuff      word      Used internally
  11949.  
  11950. FUNCTION PKillSendReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  11951.   -->    26    csCode    word     Always PKillSendReq
  11952.   -->    44    aKillQEl  pointer  Pointer to queue element
  11953.  
  11954. FUNCTION PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  11955.   -->    26    csCode    word     Always PKillGetReq
  11956.   -->    44    aKillQEl  pointer  Pointer to queue element
  11957.  
  11958. FUNCTION ATPLoad :       OSErr;
  11959. FUNCTION ATPUnload :     OSErr;
  11960. FUNCTION ATPOpenSocket   (addrRcvd: AddrBlock; VAR atpSocket: Byte) : OSErr;
  11961. FUNCTION ATPCloseSocket  (atpSocket: Byte) : OSErr;
  11962.  
  11963. FUNCTION ATPSndRequest (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  11964.   <--    abOpcode         {always tATPSndRequest}
  11965.   <--    abResult         {result code}
  11966.   -->    abUserReference  {for your use}
  11967.   -->    atpAddress       {destination socket address}
  11968.   -->    atpReqCount      {request size in bytes}
  11969.   -->    atpDataPtr       {pointer to buffer}
  11970.   -->    atpRspBDSPtr     {pointer to response BDS}
  11971.   -->    atpUserData      {user bytes}
  11972.   -->    atpXO            {exactly-once flag}
  11973.   <--    atpEOM           {end-of-message flag}
  11974.   -->    atpTimeOut       {retry timeout interval in seconds}
  11975.   -->    atpRetries       {maximum number of retries}
  11976.   -->    atpNumBufs       {number of elements in response BDS}
  11977.   <--    atpNumRsp        {number of response packets actually received}
  11978.  
  11979. FUNCTION ATPRequest (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  11980.   <--    abOpcode         {always tATPRequest}
  11981.   <--    abResult         {result code}
  11982.   -->    abUserReference  {for your use}
  11983.   -->    atpAddress       {destination socket address}
  11984.   -->    atpReqCount      {request size in bytes}
  11985.   -->    atpDataPtr       {pointer to buffer}
  11986.   <--    atpActCount      {number of bytes actually received}
  11987.   -->    atpUserData      {user bytes}
  11988.   -->    atpXO            {exactly-once flag}
  11989.   <--    atpEOM           {end-of-message flag}
  11990.   -->    atpTimeOut       {retry timeout interval in seconds}
  11991.   -->    atpRetries       {maximum number of retries}
  11992.   <--    atpRspUData      {user bytes received in transaction response}
  11993.   -->    atpRspBuf        {pointer to response message buffer}
  11994.   -->    atpRspSize       {size of response message buffer}
  11995.  
  11996. FUNCTION ATPReqCancel (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  11997.  
  11998. FUNCTION ATPGetRequest (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  11999.   <--    abOpcode         {always tATPGetRequest}
  12000.   <--    abResult         {result code}
  12001.   -->    abUserReference  {for your use}
  12002.   -->    atpSocket        {listening socket number}
  12003.   <--    atpAddress       {source socket address}
  12004.   -->    atpReqCount      {buffer size in bytes}
  12005.   -->    atpDataPtr       {pointer to buffer}
  12006.   <--    atpBitMap        {transaction bit map}
  12007.   <--    atpTransID       {transaction ID}
  12008.   <--    atpActCount      {number of bytes actually received}
  12009.   <--    atpUserData      {user bytes}
  12010.   <--    atpXO            {exactly-once flag}
  12011.  
  12012. FUNCTION ATPSndRsp (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  12013.   <--    abOpcode         {always tATPSdRsp}
  12014.   <--    abResult         {result code}
  12015.   -->    abUserReference  {for your use}
  12016.   -->    atpSocket        {responding socket number}
  12017.   -->    atpAddress       {destination socket address}
  12018.   -->    atpRspBDSPtr     {pointer to response BDS}
  12019.   -->    atpTransID       {transaction ID}
  12020.   -->    atpEOM           {end-of-message flag}
  12021.   -->    atpNumBufs       {number of response packets being sent}
  12022.   -->    atpBDSSize       {number of elements in response BDS}
  12023.  
  12024. FUNCTION ATPAddRsp (abRecord: ABRecHandle) : OSErr;
  12025.   <--    abOpcode         {always tATPAddRsp}
  12026.   <--    abResult         {result code}
  12027.   -->    abUserReference  {for your use}
  12028.   -->    atpSocket        {responding socket number}
  12029.   -->    atpAddress       {destination socket address}
  12030.   -->    atpReqCount      {buffer size in bytes}
  12031.   -->    atpDataPtr       {pointer to buffer}
  12032.   -->    atpTransID       {transaction ID}
  12033.   -->    atpUserData      {user bytes}
  12034.   -->    atpEOM           {end-of-message flag}
  12035.   -->    atpNumRsp        {sequence number}
  12036.  
  12037. FUNCTION ATPResponse (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  12038.   <--    abOpcode         {always tATPResponse}
  12039.   <--    abResult         {result code}
  12040.   -->    abUserReference  {for your use}
  12041.   -->    atpSocket        {responding socket number}
  12042.   -->    atpAddress       {destination socket address}
  12043.   -->    atpTransID       {transaction ID)
  12044.   -->    atpRspUData      {user bytes sent in transaction response}
  12045.   -->    atpRspBuf        {pointer to response message buffer}
  12046.   -->    atpRspSize       {size of response message buffer}
  12047.  
  12048. FUNCTION ATPRspCancel (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  12049.  
  12050. Name-Binding Protocol
  12051.  
  12052. FUNCTION PKillNBP (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12053.   -->    26    csCode    word     Always PKillNBP
  12054.   -->    28    nKillQEl  pointer  Pointer to queue element
  12055.  
  12056. FUNCTION NBPRegister (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  12057.   <--    abOpcode            {always tNBPRegister}
  12058.   <--    abResult            {result code}
  12059.   -->    abUserReference     {for your use}
  12060.   -->    nbpEntityPtr        {pointer to entity name}
  12061.   -->    nbpBufPtr           {pointer to buffer}
  12062.   -->    nbpBufSize          {buffer size in bytes}
  12063.   -->    nbpAddress.aSocket  {socket address}
  12064.   -->    nbpRetransmitInfo   {retransmission information}
  12065.  
  12066. FUNCTION NBPLookup (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  12067.   <--    abOpcode           {always tNBPLookup}
  12068.   <--    abResult           {result code}
  12069.   -->    abUserReference    {for your use}
  12070.   -->    nbpEntityPtr       {pointer to entity name}
  12071.   -->    nbpBufPtr          {pointer to buffer}
  12072.   -->    nbpBufSize         {buffer size in bytes}
  12073.   <->    nbpDataField       {number of addresses received}
  12074.   -->    nbpRetransmitInfo  {retransmission information}
  12075.  
  12076. FUNCTION NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne:  INTEGER;
  12077.                      VAR abEntity: EntityName; VAR address:  AddrBlock) : OSErr;
  12078.  
  12079. FUNCTION NBPConfirm (abRecord: ABRecHandle; async: BOOLEAN) : OSErr;
  12080.   <--    abOpcode           {always tNBPConfirm}
  12081.   <--    abResult           {result code}
  12082.   -->    abUserReference    {for your use}
  12083.   -->    nbpEntityPtr       {pointer to entity name}
  12084.   <--    nbpDataField       {socket number}
  12085.   -->    nbpAddress         {socket address}
  12086.   -->    nbpRetransmitInfo  {retransmission information}
  12087.  
  12088. FUNCTION NBPRemove  (abEntity: EntityPtr) : OSErr;
  12089. FUNCTION NBPLoad :   OSErr;
  12090. FUNCTION NBPUnload : OSErr;
  12091.  
  12092. AppleTalk Session Protocol
  12093.  
  12094. FUNCTION ASPOpenSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  12095.   -->    26    csCode       word       Always ASPOpenSession
  12096.   <--    28    sessRefnum   word       Session reference number
  12097.   -->    30    aspTimeout   byte       Retry interval in seconds
  12098.   -->    31    aspRetry     byte       Number of retries
  12099.   -->    32    serverAddr   long word  Server socket address
  12100.   -->    36    scbPointer   pointer    Pointer to session control block
  12101.   -->    40    attnRoutine  pointer    Pointer to attention routine
  12102.  
  12103. FUNCTION ASPCloseSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  12104.   -->    26    csCode      word  Always ASPCloseSess
  12105.   -->    28    sessRefnum  word  Session reference number
  12106.  
  12107. FUNCTION ASPAbortOS (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  12108.   -->    26    csCode           word     Always ASPAbortOS
  12109.   -->    28    abortSCBPointer  pointer  Pointer to session control block
  12110.  
  12111. FUNCTION ASPGetParms (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  12112.   -->    26    csCode          word  Always ASPGetParms
  12113.   <--    28    aspMaxCmdSize   word  Maximum size of command block
  12114.   <--    30    aspQuantumSize  word  Maximum data size
  12115.   <--    32    numSesss        word  Number of sessions
  12116.  
  12117. FUNCTION ASPCloseAll (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  12118.   -->    26    csCode  word  Always ASPCloseAll
  12119.  
  12120. FUNCTION ASPUserWrite (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  12121.   <--    18    cmdResult   long word  ASP command result
  12122.   -->    26    csCode      word       Always ASPUserWrite
  12123.   -->    28    sessRefnum  word       Session reference number
  12124.   -->    30    aspTimeout  byte       Retry interval in seconds
  12125.   -->    32    cbSize      word       Command block size
  12126.   -->    34    cbPtr       pointer    Command block pointer
  12127.   <->    38    rbSize      word       Reply buffer size and reply size
  12128.   -->    40    rbPointer   pointer    Reply buffer pointer
  12129.   <->    44    wdSize      word       Write data size
  12130.   -->    46    wdPtr       pointer    Write data pointer
  12131.   <--    50    ccbStart    record     Start of memory for CCB
  12132.  
  12133. FUNCTION ASPUserCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  12134.   <--    18    cmdResult   long word  ASP command result
  12135.   <--    26    csCode      word       Always ASPUserCommand
  12136.   <--    28    sessRefnum  word       Session number
  12137.   <--    30    aspTimeout  byte       Retry interval in seconds
  12138.   <--    32    cbSize      word       Command block size
  12139.   <--    34    cbPtr       pointer    Command block pointer
  12140.   <->    38    rbSize      word       Reply buffer and reply size
  12141.   <--    40    rbPtr       pointer    Reply buffer pointer
  12142.   <--    50    ccbStart    record     Start of memory for CCB
  12143.  
  12144. FUNCTION ASPGetStatus (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  12145.   <--    26    csCode      word       Always ASPGetStatus
  12146.   <--    30    aspTimeout  byte       Retry interval in seconds
  12147.   <--    31    aspRetry    byte       Number of retries
  12148.   <--    32    serverAddr  long word  Server socket address
  12149.   <->    38    rbSize      word       Reply buffer and reply size
  12150.   <--    40    rbPtr       pointer    Reply buffer pointer
  12151.   <--    50    ccbStart    record     Start of memory for CCB
  12152.  
  12153. General Command Format
  12154.  
  12155. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  12156.  
  12157. Parameter block
  12158.   <--    18    cmdResult   long word  AFP command result
  12159.   <--    26    csCode      word       Always AFPCall
  12160.   <--    28    sessRefnum  word       Session reference number
  12161.   <--    30    aspTimeout  byte       Retry interval in seconds
  12162.   <--    32    cbSize      word       Command buffer size
  12163.   <--    34    cbPtr       pointer    Command buffer
  12164.   <->    38    rbSize      word       Reply buffer size and reply size
  12165.   <--    40    rbPtr       pointer    Reply buffer pointer
  12166.   <->    44    wdSize      word       Write data size
  12167.   <--    46    wdPtr       pointer    Write data pointer
  12168.   <--    50    ccbStart    record     Start of memory for CCB
  12169.  
  12170. Login Command Format
  12171.  
  12172. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  12173.   <--    18    cmdResult       long word  AFP command result
  12174.   <--    26    csCode          word       Always AFPCall
  12175.   <--    28    sessRefnum      word       Session reference number
  12176.   <--    30    aspTimeout      byte       Retry interval in seconds
  12177.   <--    31    aspRetry        byte       Number of retries
  12178.   <--    32    cbSize          word       Command buffer size
  12179.   <--    34    cbPtr           pointer    Command buffer
  12180.   <->    38    rbSize          word       Reply buffer size and reply size
  12181.   <--    40    rbPtr           pointer    Reply buffer pointer
  12182.   <--    44    afpAddrBlock    long word  Server address block
  12183.   <->    48    afpSCBPtr       pointer    SCB pointer
  12184.   <->    52    afpAttnRoutine  pointer    Attention routine pointer
  12185.   <--    50    ccbStart        record     Start of command control block
  12186.  
  12187. AFPWrite Command Format
  12188.  
  12189. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  12190.   <--    18    cmdResult   long word  AFP command result
  12191.   <--    26    csCode      word       Always AFPCall
  12192.   <--    28    sessRefnum  word       Session number
  12193.   <--    30    aspTimeout  byte       Retry interval in seconds
  12194.   <--    32    cbSize      word       Command buffer size
  12195.   <--    34    cbPtr       pointer    Command buffer
  12196.   <->    38    rbSize      word       Reply buffer size and reply size
  12197.   <--    40    rbPtr       pointer    Reply buffer pointer
  12198.   <--    44    wdSize      word       (used internally)
  12199.   <->    46    wdPtr       pointer    Write data pointer  (updated)
  12200.   <--    50    ccbStart    record     Start of memory for CCB
  12201.  
  12202. Command Block Structure
  12203.  
  12204.   <--    0    cmdByte       byte       AFP call command byte
  12205.   <--    1    startEndFlag  byte       Start/end Flag
  12206.   <->    4    rwOffset      long word  Offset within fork to write
  12207.   <->    8    reqCount      long word  Requested count
  12208.  
  12209. AFPRead Command Format
  12210.  
  12211. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
  12212.   <--    18    cmdResult   long word  ASP command result
  12213.   <--    26    csCode      word       Always AFPCall
  12214.   <--    28    sessRefnum  word       Session number
  12215.   <--    30    aspTimeout  byte       Retry interval in seconds
  12216.   <--    32    cbSize      word       Command buffer size
  12217.   <--    34    cbPtr       pointer    Command buffer
  12218.   <--    38    rbSize      word       Used internally
  12219.   <->    40    rbPtr       pointer    Reply buffer pointer (updated)
  12220.   <--    50    ccbStart    record     Start of memory for CCB
  12221.  
  12222. Command Block Structure
  12223.  
  12224.   <--    0    cmdByte      byte       AFP call command byte
  12225.   <->    4    rwOffset     long word  Offset within fork to read
  12226.   <->    8    reqCount     long word  Requested count
  12227.   <--    12   newLineFlag  byte       Newline Flag
  12228.   <--    13   newLineChar  byte       Newline Character
  12229.  
  12230. Miscellaneous Routines
  12231.  
  12232. FUNCTION GetNodeAddress (VAR myNode,myNet: INTEGER) : OSErr;
  12233. FUNCTION IsMPPOpen :     BOOLEAN;
  12234. FUNCTION IsATPOpen :     BOOLEAN;
  12235.  
  12236. FUNCTION PSetSelfSend (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12237.   -->    26    csCode       word  Always PSetSelfSend
  12238.   -->    28    newSelfFlag  byte  New SelfSend flag
  12239.   <--    29    oldSelfFlag  byte  Old SelfSend flag
  12240.  
  12241. _______________________________________________________________________________
  12242.  
  12243. Result Codes
  12244.  
  12245. Name            Value    Meaning
  12246. atpBadRsp       –3107    Bad response from ATPRequest
  12247. atpLenErr       –3106    ATP response message too large
  12248. badATPSkt       –1099    ATP bad responding socket
  12249. badBuffNum      –1100    ATP bad sequence number
  12250. buf2SmallErr    –3101    ALAP frame too large for buffer DDP datagram
  12251.                          too large for buffer
  12252. cbNotFound      –1102    ATP control block not found
  12253. cksumErr        –3103    DDP bad checksum
  12254. ddpLenErr         –92    DDP datagram or ALAP data length too big
  12255. ddpSktErr         –91    DDP socket error: socket already active; not a
  12256.                          well-known socket; socket table full; all dynamic
  12257.                          socket numbers in use
  12258. excessCollsns     –95    ALAP no CTS received after 32 RTS's, or line
  12259.                          sensed in use 32 times (not necessarily caused
  12260.                          by collisions)
  12261. extractErr      –3104    NBP can't find tuple in buffer
  12262. lapProtErr        –94    ALAP error attaching/detaching ALAP protocol type:
  12263.                          attach error when ALAP protocol type is negative,
  12264.                          not in range, already in table, or when table is full;
  12265.                          detach error when ALAP protocol type isn't in table
  12266. nbpBuffOvr      –1024    NBP buffer overflow
  12267. nbpConfDiff     –1026    NBP name confirmed for different socket
  12268. nbpDuplicate    –1027    NBP duplicate name already exists
  12269. nbpNISErr       –1029    NBP names information socket error
  12270. nbpNoConfirm    –1025    NBP name not confirmed
  12271. nbpNotFound     –1028    NBP name not found
  12272. noBridgeErr       –93    No bridge found
  12273. noDataArea      –1104    Too many outstanding ATP calls
  12274. noErr               0    No error
  12275. noMPPError      –3102    MPP driver not installed
  12276. noRelErr        –1101    ATP no release received
  12277. noSendResp      –1103    ATPAddRsp issued before ATPSndRsp
  12278. portInUse         –97    Driver Open error, port already in use
  12279. portNotCf         –98    Driver Open error, port not configured
  12280.                          for this connection
  12281. readQErr        –3105    Socket or protocol type invalid or not found in table
  12282. recNotFnd       –3108    ABRecord not found
  12283. reqAborted      –1105    Request aborted
  12284. reqFailed       –1096    ATPSndRequest failed: retry count exceeded
  12285. sktClosedErr    –3109    Asynchronous call aborted because socket was
  12286.                          closed before call was completed
  12287. tooManyReqs     –1097    ATP too many concurrent requests
  12288. tooManySkts     –1098    ATP too many responding sockets
  12289.  
  12290. _______________________________________________________________________________
  12291.  
  12292. Assembly-Language Information
  12293.  
  12294. Constants
  12295.  
  12296. ; Serial port use types
  12297.  
  12298. useFree       .EQU    0     ;unconfigured
  12299. useATalk      .EQU    1     ;configured for AppleTalk
  12300. useASync      .EQU    2     ;configured for the Serial Driver
  12301.  
  12302. ; Bit in PortBUse for .ATP driver status
  12303.  
  12304. atpLoadedBit  .EQU    4     ;set if .ATP driver is opened
  12305.  
  12306. ; Unit numbers for AppleTalk drivers
  12307.  
  12308. mppUnitNum    .EQU    9     ;.MPP driver
  12309. atpUnitNum    .EQU    10    ;.ATP driver
  12310.  
  12311. ; csCode values for Control calls (MPP)
  12312.  
  12313. writeLAP      .EQU    243
  12314. detachPH      .EQU    244
  12315. attachPH      .EQU    245
  12316. writeDDP      .EQU    246
  12317. closeSkt      .EQU    247
  12318. openSkt       .EQU    248
  12319. loadNBP       .EQU    249
  12320. confirmName   .EQU    250
  12321. lookupName    .EQU    251
  12322. removeName    .EQU    252
  12323. registerName  .EQU    253
  12324. killNBP       .EQU    254
  12325. unloadNBP     .EQU    255
  12326.  
  12327. ; csCode values for Control calls (ATP)
  12328.  
  12329. relRspCB      .EQU    249
  12330. closeATPSkt   .EQU    250
  12331. addResponse   .EQU    251
  12332. sendResponse  .EQU    252
  12333. getRequest    .EQU    253
  12334. openATPSkt    .EQU    254
  12335. sendRequest   .EQU    255
  12336. relTCB        .EQU    256
  12337.  
  12338. ; ALAP header
  12339.  
  12340. lapDstAdr     .EQU    0     ;destination node ID
  12341. lapSrcAdr     .EQU    1     ;source node ID
  12342. lapType       .EQU    2     ;ALAP protocol type
  12343.  
  12344. ; ALAP header size
  12345.  
  12346. lapHdSz       .EQU    3
  12347.  
  12348. ; ALAP protocol type values
  12349.  
  12350. shortDDP      .EQU    1     ;short DDP header
  12351. longDDP       .EQU    2     ;long DDP header
  12352.  
  12353. ; Long DDP header
  12354.  
  12355. ddpHopCnt     .EQU    0     ;count of bridges passed (4 bits)
  12356. ddpLength     .EQU    0     ;datagram length (10 bits)
  12357. ddpChecksum   .EQU    2     ;checksum
  12358. ddpDstNet     .EQU    4     ;destination network number
  12359. ddpSrcNet     .EQU    6     ;source network number
  12360. ddpDstNode    .EQU    8     ;destination node ID
  12361. ddpSrcNode    .EQU    9     ;source node ID
  12362. ddpDstSkt     .EQU    10    ;destination socket number
  12363. ddpSrcSkt     .EQU    11    ;source socket number
  12364. ddpType       .EQU    12    ;DDP protocol type
  12365.  
  12366. ; DDP long header size
  12367.  
  12368. ddpHSzLong    .EQU    ddpType+1
  12369.  
  12370. ; Short DDP header
  12371.  
  12372. ddpLength     .EQU    0               ;datagram length
  12373. sDDPDstSkt    .EQU    ddpChecksum     ;destination socket number
  12374. sDDPSrcSkt    .EQU    sDDPDstSkt+1    ;source socket number
  12375. sDDPType      .EQU    sDDPSrcSkt+1    ;DDP protocol type
  12376.  
  12377. ; DDP short header size
  12378.  
  12379. ddpHSzShort   .EQU    sDDPType+1
  12380.  
  12381. ; Mask for datagram length
  12382.  
  12383. ddpLenMask    .EQU    $03FF
  12384.  
  12385. ; Maximum size of DDP data
  12386.  
  12387. ddpMaxData    .EQU    586
  12388.  
  12389. ; ATP header
  12390.  
  12391. atpControl    .EQU    0     ;control information
  12392. atpBitMap     .EQU    1     ;bit map
  12393. atpRespNo     .EQU    1     ;sequence number
  12394. atpTransID    .EQU    2     ;transaction ID
  12395. atpUserData   .EQU    4     ;user bytes
  12396.  
  12397. ; ATP header size
  12398.  
  12399. atpHdSz       .EQU    8
  12400.  
  12401. ; DDP protocol type for ATP packets
  12402.  
  12403. atp           .EQU    3
  12404.  
  12405. ; ATP function code
  12406.  
  12407. atpReqCode    .EQU    $40    ;TReq packet
  12408. atpRspCode    .EQU    $80    ;TResp packet
  12409. atpRelCode    .EQU    $C0    ;TRel packet
  12410.  
  12411. ; ATPFlags control information bits
  12412.  
  12413. sendChk       .EQU    0     ;send-checksum bit
  12414. tidValid      .EQU    1     ;transaction ID validity bit
  12415. atpSTSBit     .EQU    3     ;send-transmission-status bit
  12416. atpEOMBit     .EQU    4     ;end-of-message bit
  12417. atpXOBit      .EQU    5     ;exactly-once bit
  12418.  
  12419. ; Maximum number of ATP request packets
  12420.  
  12421. atpMaxNum     .EQU    8
  12422.  
  12423. ; ATP buffer data structure
  12424.  
  12425. bdsBuffSz     .EQU    0     ;size of data to send or buffer size
  12426. bdsBuffAddr   .EQU    2     ;pointer to data or buffer
  12427. bdsDataSz     .EQU    6     ;number of bytes actually received
  12428. bdsUserData   .EQU    8     ;user bytes
  12429.  
  12430. ; BDS element size
  12431.  
  12432. bdsEntrySz    .EQU    12
  12433.  
  12434. ; NBP packet
  12435.  
  12436. nbpControl    .EQU    0     ;packet type
  12437. nbpTCount     .EQU    0     ;tuple count
  12438. nbpID         .EQU    1     ;packet identifier
  12439. nbpTuple      .EQU    2     ;start of first tuple
  12440.  
  12441. ; DDP protocol type for NBP packets
  12442.  
  12443. nbp           .EQU    2
  12444.  
  12445. ; NBP packet types
  12446.  
  12447. brRq          .EQU    1     ;broadcast request
  12448. lkUp          .EQU    2     ;lookup request
  12449. lkUpReply     .EQU    3     ;lookup reply
  12450.  
  12451. ; NBP tuple
  12452.  
  12453. tupleNet      .EQU    0     ;network number
  12454. tupleNode     .EQU    2     ;node ID
  12455. tupleSkt      .EQU    3     ;socket number
  12456. tupleEnum     .EQU    4     ;used internally
  12457. tupleName     .EQU    5     ;entity name
  12458.  
  12459. ; Maximum number of tuples in NBP packet
  12460.  
  12461. tupleMax      .EQU    15
  12462.  
  12463. ; NBP meta-characters
  12464.  
  12465. equals        .EQU    '='    ;"wild-card" meta-character
  12466. star          .EQU    '*'    ;"this zone" meta-character
  12467.  
  12468. ; NBP names table entry
  12469.  
  12470. ntLink        .EQU    0     ;pointer to next entry
  12471. ntTuple       .EQU    4     ;tuple
  12472. ntSocket      .EQU    7     ;socket number
  12473. ntEntity      .EQU    9     ;entity name
  12474.  
  12475. ; NBP names information socket number
  12476.  
  12477. nis           .EQU    2
  12478.  
  12479. Offsets in User Bytes
  12480.  
  12481. aspCmdCode      EQU     0      ;offset to command field
  12482. aspWSSNum       EQU     1      ;WSS number in OpenSessions
  12483. aspVersNum      EQU     2      ;ASP version number in OpenSessions
  12484. aspSSSNum       EQU     0      ;SSS number in OpenSessReplies
  12485. aspSessID       EQU     1      ;session ID (requests &OpenSessReply)
  12486. aspOpenErr      EQU     2      ;OpenSessReply error code
  12487.  
  12488. aspSeqNum       EQU     2      ;sequence number in requests
  12489. aspAttnCode     EQU     2      ;attention bytes in attentions
  12490.  
  12491. Offsets in ATP data part
  12492.  
  12493. aspWrBSize      EQU     0             ;offset to write buffer size (WriteData)
  12494. aspWrHdrSz      EQU     ASPWrBSize+2  ;size of data part
  12495.  
  12496. ASP command codes
  12497.  
  12498. aspCloseSess    EQU     1       ;close session
  12499. aspCommand      EQU     2       ;user-command
  12500. aspGetStat      EQU     3       ;get status
  12501. aspOpenSess     EQU     4       ;open session
  12502. aspTickle       EQU     5       ;tickle
  12503. aspWrite        EQU     6       ;write
  12504. aspDataWrite    EQU     7       ;writedata (from server)
  12505. aspAttention    EQU     8       ;attention (from server)
  12506.  
  12507. ASP miscellaneous
  12508.  
  12509. aspVersion      EQU     $0100                 ;ASP version number
  12510. MaxCmdSize      EQU     ATPMaxData            ;maximum command block size
  12511. QuantumSize     EQU     ATPMaxData*ATPMaxNum  ;maximum reply size
  12512. XPPLoadedBit    EQU     ATPLoadedBit+1        ;XPP bit in PortBUse
  12513. XPPUnitNum      EQU     40                    ;unit number for XPP (old ROMs)
  12514.  
  12515. ASP errors codes
  12516.  
  12517. aspBadVersNum   EQU  -1066  ;server cannot support this ASP version
  12518. aspBufTooSmall  EQU  -1067  ;buffer too small
  12519. aspNoMoreSess   EQU  -1068  ;no more sessions on server
  12520. aspNoServers    EQU  -1069  ;no servers at that address
  12521. aspParamErr     EQU  -1070  ;parameter error
  12522. aspServerBusy   EQU  -1071  ;server cannot open another session
  12523. aspSessClosed   EQU  -1072  ;session closed
  12524. aspSizeErr      EQU  -1073  ;command block too big
  12525. aspTooMany      EQU  -1074  ;too many clients
  12526. aspNoAck        EQU  -1075  ;no ack on attention Request
  12527.  
  12528. Control codes
  12529.  
  12530. openSess       EQU    255    ;open session
  12531. closeSess      EQU    254    ;close session
  12532. userCommand    EQU    253    ;user command
  12533. userWrite      EQU    252    ;user write
  12534. getStatus      EQU    251    ;get status
  12535. afpCall        EQU    250    ;AFP command (buffer has command code)
  12536. getParms       EQU    249    ;get parameters
  12537. abortOS        EQU    248    ;abort open session request
  12538. closeAll       EQU    247    ;close all open sessions
  12539.  
  12540. ASP queue element standard structure:  arguments passed in the CSParam area
  12541.  
  12542. sessRefnum      EQU     $1C   ;offset to session refnum [word]
  12543. aspTimeout      EQU     $1E   ;timeout for ATP [byte]
  12544. aspRetry        EQU     $1F   ;retry count for ATP [byte]
  12545. serverAddr      EQU     $20   ;server address block [longword]
  12546. scbPointer      EQU     $24   ;SCB pointer [longword]
  12547. attnRoutine     EQU     $28   ;attention routine pointer [long]
  12548.  
  12549. cbSize          EQU     $20   ;command block size [word]
  12550. cbPtr           EQU     $22   ;command block pointer [long]
  12551. rbSize          EQU     $26   ;reply buffer size [word]
  12552. rbPtr           EQU     $28   ;reply buffer pointer [long]
  12553. wdSize          EQU     $2C   ;write data size [word]
  12554. wdPtr           EQU     $2E   ;write data pointer [long]
  12555. ccbStart        EQU     $32   ;start of memory for CCB
  12556.  
  12557. aspMaxCmdSize   EQU     $1C   ;for SPGetParms [word]
  12558. aspQuantumSize  EQU     $1E   ;for SPGetParms [word]
  12559. abortSCBPtr     EQU     $1F   ;SCB pointer for AbortOS [long]
  12560.  
  12561. cmdResult       EQU     $12   ;command result (ATP user
  12562.                               ; bytes)[long]
  12563.  
  12564. afpAddrBlock    EQU     $2C   ;address block in AFP login[long]
  12565. afpSCBPtr       EQU     $30   ;SCB pointer in AFP login [long]
  12566. afpAttnRoutine  EQU     $34   ;attn routine pointer in AFP login
  12567.  
  12568. scbMemSize      EQU     $C0   ;size of memory for SCB
  12569.  
  12570. AFPCall command codes
  12571.  
  12572. afpLogin           EQU   18;
  12573. afpContLogin       EQU   19;
  12574. afpLogout          EQU   20;
  12575. afpRead            EQU   27;
  12576. afpWrite           EQU   33;
  12577.  
  12578. Offsets for certain parameters in Read/Write calls
  12579.  
  12580. startEndFlag   EQU    $1 ;write only; offset relative to start or end
  12581. rwOffset       EQU    $4 ;offset at which to start read or write
  12582. reqCount       EQU    $8 ;count of bytes to read or write
  12583. newLineFlag    EQU    $C ;read only; newline character flag
  12584. newLineChar    EQU    $D ;read only; newline character
  12585. lastWritten    EQU    $0 ;write only; last written  (returned)
  12586.  
  12587. Miscellaneous
  12588.  
  12589. afpUseWrite  EQU  $C0  ;first call in range that maps to an
  12590.                        ; ASPWrite
  12591.  
  12592. Routines
  12593.  
  12594. Preferred Interface Routines
  12595.  
  12596. AttachPH     Function PAttachPH    (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12597. DetachPH     Function PDetachPH    (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12598. WriteLAP     Function PWriteLAP    (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12599. OpenSkt      Function POpenSkt     (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12600. CloseSkt     Function PCloseSkt    (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12601. WriteDDP     Function PWriteDDP    (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12602. RegisterName Function PRegisterName(thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12603. LookupName   Function PLookupName  (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12604. ConfirmName  Function PConfirmName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12605. RemoveName   Function PRemoveName  (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12606. OpenATPSkt   Function POpenATPSkt  (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12607. CloseATPSkt  Function PCloseATPSkt (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12608. SendRequest  Function PSendRequest (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12609. GetRequest   Function PGetRequest  (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12610. SendResponse Function PSendResponse(thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12611. AddResponse  Function PAddResponse (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12612. ReLTCB       Function PRelTCB      (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12613. RelRspCB     Function PRelRspCB    (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12614. SetSelfSend  Function PSetSelfSend (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12615. NSendRequest Function PNSendRequest(thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12616. KillSendReq  Function PKillSendReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12617. KillGetReq   Function PKillGetReq  (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  12618. KillNBP      Function PKillNBP     (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  12619.  
  12620. PROCEDURE BuildLAPwds (wdsPtr,dataPtr: Ptr;
  12621.                        destHost,protoType,frameLen: INTEGER);
  12622. PROCEDURE BuildDDPwds  (wdsPtr,headerPtr,dataPtr: Ptr; destAddress: AddrBlock;
  12623.                         DDPType : INTEGER; dataLen: INTEGER);
  12624. PROCEDURE NBPSetEntity (buffer: Ptr; nbpObject,nbpType,nbpZone: Str32);
  12625. PROCEDURE NBPSetNTE (ntePtr: Ptr; nbpObject,nbpType,nbpZone: Str32;
  12626.                      Socket: INTEGER);
  12627. FUNCTION  NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne: INTEGER;
  12628.                       VAR abEntity: EntityName; VAR address: AddrBlock) : OSErr;
  12629. FUNCTION  GetBridgeAddress: INTEGER;
  12630. FUNCTION  BuildBDS (buffPtr,bdsPtr: Ptr; buffSize: INTEGER) : INTEGER;
  12631.  
  12632. Alternate Interface Routines
  12633.  
  12634. Link Access Protocol
  12635.  
  12636. WriteLAP function
  12637.   -->    26    csCode      word     ;always writeLAP
  12638.   -->    30    wdsPointer  pointer  ;write data structure
  12639.  
  12640. AttachPH function
  12641.   -->    26    csCode    word     ;always attachPH
  12642.   -->    28    protType  byte     ;ALAP protocol type
  12643.   -->    30    handler   pointer  ;protocol handler
  12644.  
  12645. DetachPH function
  12646.   -->    26    csCode    word  ;always detachPH
  12647.   -->    28    protType  byte  ;ALAP protocol type
  12648.  
  12649. Datagram Delivery Protocol
  12650.  
  12651. OpenSkt function
  12652.   -->    26    csCode    word     ;always openSkt
  12653.   <->    28    socket    byte     ;socket number
  12654.   -->    30    listener  pointer  ;socket listener
  12655.  
  12656. CloseSkt function
  12657.   -->    26    csCode  word  ;always closeSkt
  12658.   -->    28    socket  byte  ;socket number
  12659.  
  12660. WriteDDP function
  12661.   -->    26    csCode        word     ;always writeDDP
  12662.   -->    28    socket        byte     ;socket number
  12663.   -->    29    checksumFlag  byte     ;checksum flag
  12664.   -->    30    wdsPointer    pointer  ;write data structure
  12665.  
  12666. AppleTalk Transaction Protocol
  12667.  
  12668. OpenATPSkt function
  12669.   -->    26    csCode     word       ;always openATPSkt
  12670.   <->    28    atpSocket  byte       ;socket number
  12671.   -->    30    addrBlock  long word  ;socket request specification
  12672.  
  12673. CloseATPSkt function
  12674.   -->    26    csCode     word  ;always closeATPSkt
  12675.   -->    28    atpSocket  byte  ;socket number
  12676.  
  12677. SendRequest function
  12678.   -->    18    userData    long word  ;user bytes
  12679.   <--    22    reqTID      word       ;transaction ID used in request
  12680.   -->    26    csCode      word       ;always sendRequest
  12681.   <--    28    currBitMap  byte       ;bit map
  12682.   <->    29    atpFlags    byte       ;control information
  12683.   -->    30    addrBlock   long word  ;destination socket address
  12684.   -->    34    reqLength   word       ;request size in bytes
  12685.   -->    36    reqPointer  pointer    ;pointer to request data
  12686.   -->    40    bdsPointer  pointer    ;pointer to response BDS
  12687.   -->    44    numOfBuffs  byte       ;number of responses expected
  12688.   -->    45    timeOutVal  byte       ;timeout interval
  12689.   <--    46    numOfResps  byte       ;number of responses received
  12690.   <->    47    retryCount  byte       ;number of retries
  12691.  
  12692. GetRequest function
  12693.   <--    18    userData    long word  ;user bytes
  12694.   -->    26    csCode      word       ;always getRequest
  12695.   -->    28    atpSocket   byte       ;socket number
  12696.   <--    29    atpFlags    byte       ;control information
  12697.   <--    30    addrBlock   long word  ;source of request
  12698.   <->    34    reqLength   word       ;request buffer size
  12699.   -->    36    reqPointer  pointer    ;pointer to request buffer
  12700.   <--    44    bitMap      byte       ;bit map
  12701.   <--    46    transID     word       ;transaction ID
  12702.  
  12703. SendResponse function
  12704.   <--    18    userData    long word  ;user bytes from TRel
  12705.   -->    26    csCode      word       ;always sendResponse
  12706.   -->    28    atpSocket   byte       ;socket number
  12707.   -->    29    atpFlags    byte       ;control information
  12708.   -->    30    addrBlock   long word  ;response destination
  12709.   -->    40    bdsPointer  pointer    ;pointer to response BDS
  12710.   -->    44    numOfBuffs  byte       ;number of response packets being sent
  12711.   -->    45    bdsSize     byte       ;BDS size in elements
  12712.   -->    46    transID     word       ;transaction ID
  12713.  
  12714. AddResponse function
  12715.   -->    18    userData    long word  ;user bytes
  12716.   -->    26    csCode      word       ;always addResponse
  12717.   -->    28    atpSocket   byte       ;socket number
  12718.   -->    29    atpFlags    byte       ;control information
  12719.   -->    30    addrBlock   long word  ;response destination
  12720.   -->    34    reqLength   word       ;response size
  12721.   -->    36    reqPointer  pointer    ;pointer to response
  12722.   -->    44    rspNum      byte       ;sequence number
  12723.   -->    46    transID     word       ;transaction ID
  12724.  
  12725. RelTCB function
  12726.   -->    26    csCode     word       ;always relTCB
  12727.   -->    30    addrBlock  long word  ;destination of request
  12728.   -->    46    transID    word       ;transaction ID of request
  12729.  
  12730. RelRspCB function
  12731.   -->    26    csCode     word       ;always relRspCB
  12732.   -->    28    atpSocket  byte       ;socket number that request was
  12733.                                      ; received on
  12734.   -->    30    addrBlock  long word  ;source of request
  12735.   -->    46    transID    word       ;transaction ID of request
  12736.  
  12737. Name-Binding Protocol
  12738.  
  12739. RegisterName function
  12740.   -->    26    csCode      word     ;always registerName
  12741.   -->    28    interval    byte     ;retry interval
  12742.   <->    29    count       byte     ;retry count
  12743.   -->    30    ntQElPtr    pointer  ;names table element pointer
  12744.   -->    34    verifyFlag  byte     ;set if verify needed
  12745.  
  12746. LookupName function
  12747.   -->    26    csCode       word     ;always lookupName
  12748.   -->    28    interval     byte     ;retry interval
  12749.   <->    29    count        byte     ;retry count
  12750.   -->    30    entityPtr    pointer  ;pointer to entity name
  12751.   -->    34    retBuffPtr   pointer  ;pointer to buffer
  12752.   -->    38    retBuffSize  word     ;buffer size in bytes
  12753.   -->    40    maxToGet     word     ;matches to get
  12754.   <--    42    numGotten    word     ;matches found
  12755.  
  12756. ConfirmName function
  12757.   -->    26    csCode       word     ;always confirmName
  12758.   -->    28    interval     byte     ;retry interval
  12759.   <->    29    count        byte     ;retry count
  12760.   -->    30    entityPtr    pointer  ;pointer to entity name
  12761.   -->    34    confirmAddr  pointer  ;entity address
  12762.   <--    38    newSocket    byte     ;socket number
  12763.  
  12764. RemoveName function
  12765.   -->    26    csCode     word     ;always removeName
  12766.   -->    30    entityPtr  pointer  ;pointer to entity name
  12767.  
  12768. LoadNBP function
  12769.   -->    26    csCode  word  ;always loadNBP
  12770.  
  12771. UnloadNBP function
  12772.   -->    26    csCode  word  ;always unloadNB
  12773.  
  12774. Variables
  12775.  
  12776. SPConfig    Use types for serial ports (byte)
  12777.             (bits 0-3:  current configuration of serial port B
  12778.              bits 4-6:  current configuration of serial port A)
  12779. PortBUse    Current availability of serial port B (byte)
  12780.             (bit 7:  1 = not in use, 0 = in use bits
  12781.              bits 0-3:  current use of port bits
  12782.              bits 4-6:  driver-specific)
  12783. ABusVars    Pointer to AppleTalk variables
  12784.  
  12785. Further Reference:
  12786. _______________________________________________________________________________
  12787. Toolbox Event Manager
  12788. Device Manager
  12789. Technical Note #9, Will Your AppleTalk Application Support Internets?
  12790. Technical Note #20, Data Servers on AppleTalk
  12791. Technical Note #121, Using the High-Level AppleTalk Routines
  12792. Technical Note #132, AppleTalk Interface Update
  12793. Technical Note #142, Avoid Use of Network Events
  12794. Technical Note #195, ASP and AFP Description Discrepancies
  12795. Technical Note #199, KillNBP Clarification
  12796. Technical Note #201, ReadPacket Clarification
  12797. Technical Note #224, Opening AppleTalk
  12798. Technical Note #225, Using RegisterName
  12799. Technical Note #250, AppleTalk Phase 2 on the Macintosh
  12800. “Inside AppleTalk”
  12801.  
  12802. æKY BinaryDecimalConversion
  12803. æC 
  12804. THE BINARY-DECIMAL CONVERSION PACKAGE
  12805. _______________________________________________________________________________
  12806.  
  12807. About…The…Binary-DecimalConversion…Chapter
  12808. Binary-Decimal…Conversion…Package…Routines
  12809. Summary…of…the…Binary-Decimal…Conversion…Package
  12810. _______________________________________________________________________________
  12811.  
  12812.  
  12813.  
  12814. æKY About…The…Binary-DecimalConversion…Chapter
  12815. æC »ABOUT THIS CHAPTER                                BinaryDecimalConversion
  12816. _______________________________________________________________________________
  12817.  
  12818. This chapter describes the Binary-Decimal Conversion Package, which contains five
  12819. routines.  One converts an integer from its internal (binary) form to a string that
  12820. represents its decimal (base 10) value; the other converts a decimal string to the
  12821. corresponding integer.
  12822.  
  12823. Three new routines have been added to the Binary-Decimal Conversion Package for the
  12824. Macintosh Plus. These routines supplement the Floating-Point Arithmetic and Transcendental
  12825. Functions Packages in providing the the Standard Apple Numeric Environment (SANE) for
  12826. the Macintosh.
  12827.  
  12828. Detailed documentation for these new routines is included with the rest of the SANE
  12829. documentation in the Apple Numerics Manual—in particular, see the chapter
  12830. “Conversions” in Part I and the three chapters “Conversions”, “Numeric Scanner and
  12831. Formatter”, and “Examples” in Part III.
  12832.  
  12833. The new routines, two numeric scanners and a numeric formatter, are intended for
  12834. programmers with special needs beyond what their development language provides. For
  12835. example, developers of programming languages can use these routines to implement the
  12836. floating-point I/O routines—such as read and write for Pascal or scanf and printf for
  12837. C—that are appropriate for their particular languages. The scanners can be used for
  12838. scanning numbers embedded in text and for numbers received character by character.
  12839. The scanners differ only in that one accepts a pointer to a Pascal strings (with an
  12840. initial length byte) as input, while the other accepts a pointer to the first character
  12841. of a character stream.
  12842.  
  12843. The scanners convert ASCII string representations of numbers into SANE decimal records.
  12844. The formatter converts SANE decimal records into ASCII string representations. The
  12845. Floating-Point Arithmetic Package converts between this decimal record format and the
  12846. SANE binary data formats.
  12847.  
  12848. The three routines handle the usual number representations, like –1.234 and
  12849. 5e–7, throughout the range and precision of the extended data format. They also
  12850. handle the special NaN, infinity, and signed-zero representations specified by the
  12851. IEEE Floating-Point Standard.
  12852.  
  12853. You should already be familiar with packages in general, as described in the Package
  12854. Manager chapter.
  12855.  
  12856. _______________________________________________________________________________
  12857.  
  12858.  
  12859. æKY Binary-Decimal…Conversion…Package…Routines
  12860. æC »BINARY-DECIMAL CONVERSION PACKAGE ROUTINES        BinaryDecimalConversion
  12861. _______________________________________________________________________________
  12862.  
  12863. The Binary-Decimal Conversion Package is contained in the ROM, beginning with the
  12864. 128K ROM. The routines are register-based, so the Pascal form of each is followed by
  12865. a box containing information needed to use the routine from assembly language.
  12866.  
  12867. Assembly-language note:  The trap macro for the Binary-Decimal Conversion
  12868.                          Package is _Pack7. The routine selectors are as
  12869.                          follows:
  12870.  
  12871.                            numToString    .EQU    0
  12872.                            stringToNum    .EQU    1
  12873.  
  12874. PROCEDURE NumToString (theNum:  LONGINT; VAR theString:  Str255);
  12875.  
  12876. On entry    A0:  pointer to theString (preceded by length byte)
  12877.             D0:  theNum (long word)
  12878. On exit     A0:  pointer to theString
  12879.  
  12880. NumToString converts theNum to a string that represents its decimal value, and returns
  12881. the result in theString. If the value is negative, the string begins with a minus
  12882. sign; otherwise, the sign is omitted. Leading zeroes are suppressed, except that the
  12883. value 0 produces '0'. For example:
  12884.  
  12885.   theNum     theString
  12886.  
  12887.     12         '12'
  12888.    –23        '–23'
  12889.      0          '0'
  12890.  
  12891. PROCEDURE StringToNum (theString:  Str255; VAR theNum:  LONGINT);
  12892.  
  12893. On entry    A0:  pointer to theString (preceded by length byte)
  12894. On exit     D0:  theNum (long word)
  12895.  
  12896. Given a string representing a decimal integer, StringToNum converts it to the corresponding
  12897. integer and returns the result in theNum. The string may begin with a plus or minus
  12898. sign. For example:
  12899.  
  12900.   theString     theNum
  12901.  
  12902.     '12'          12
  12903.    '–23'         –23
  12904.     '–0'           0
  12905.    '055'          55
  12906.  
  12907. The magnitude of the integer is converted modulo 2^32, and the 32-bit result is
  12908. negated if the string begins with a minus sign; integer overflow occurs if the magnitude
  12909. is greater than 2^31–1. (Negation is done by taking the two’s complement—reversing
  12910. the state of each bit and then adding 1.) For example:
  12911.  
  12912.   theString                               theNum
  12913.  
  12914.   '2147483648' (magnitude is 2^31)      –2147483648
  12915.  '–2147483648'                          –2147483648
  12916.   '4294967295' (magnitude is 2^32–1)    –1
  12917.  '–4294967295'                           1
  12918.  
  12919. StringToNum doesn’t actually check whether the characters in the string are between
  12920. '0' and '9'; instead, since the ASCII codes for '0' through '9' are $30 through $39,
  12921. it just masks off the last four bits and uses them as a digit. For example, '2:' is
  12922. converted to the number 30 because the ASCII code for ':' is $3A. Spaces are treated
  12923. as zeroes, since the ASCII code for a space is $20. Given that the ASCII codes for
  12924. 'C', 'A', and 'T' are $43, $41, and $54, respectively, consider the following examples:
  12925.  
  12926.   theString     theNum
  12927.  
  12928.     'CAT'        314
  12929.    '+CAT'        314
  12930.    '–CAT'       –314
  12931.  
  12932. _______________________________________________________________________________
  12933.  
  12934.  
  12935. æKY Summary…of…the…Binary-Decimal…Conversion…Package
  12936. æC »SUMMARY OF THE BINARY-DECIMAL CONVERSION PACKAGE  BinaryDecimalConversion
  12937. _______________________________________________________________________________
  12938.  
  12939. Routines
  12940.  
  12941. PROCEDURE NumToString (theNum:  LONGINT; VAR theString:  Str255);
  12942. PROCEDURE StringToNum (theString:  Str255; VAR theNum:  LONGINT);
  12943.  
  12944. _______________________________________________________________________________
  12945.  
  12946. Assembly-Language Information
  12947.  
  12948. Constants
  12949.  
  12950. ; Routine selectors
  12951.  
  12952. numToString  .EQU  0
  12953. stringToNum  .EQU  1
  12954.  
  12955. Routines
  12956.  
  12957. Name           On entry                          On exit
  12958.  
  12959. NumToString    A0:  ptr to theString             A0:  ptr to theString
  12960.                     (preceded by length byte)
  12961.                D0:  theNum (long)
  12962. StringToNum    A0:  ptr to theString             D0:  theNum (long)
  12963.                     (preceded by length byte)
  12964.  
  12965. Trap Macro Name
  12966.  
  12967. _Pack7
  12968.  
  12969.  
  12970. æKY ColorManager
  12971. æC 
  12972. THE COLOR MANAGER                                                  
  12973. _______________________________________________________________________________
  12974.  
  12975. About…The…ColorManager…Chapter
  12976. About…the…Color…Manager
  12977. Using…the…Color…Manager
  12978. Color…Manager…Routines
  12979. Custom…Search…and…Complement…Functions
  12980. Summary…of…the…Color…Manager
  12981. _______________________________________________________________________________
  12982.  
  12983.  
  12984.  
  12985. æKY About…The…ColorManager…Chapter
  12986. æC »ABOUT THIS CHAPTER                                           ColorManager
  12987. _______________________________________________________________________________
  12988.  
  12989. The Color Manager supplies color-selection support for Color QuickDraw on the Macintosh
  12990. II. The software described in this chapter allows specialized applications to fine-tune
  12991. the color-matching algorithms, and also provides utility functions that are rarely
  12992. used by applications.
  12993.  
  12994. An understanding of Color QuickDraw concepts, terminology, and data structures is
  12995. essential when using the material in this chapter. You should be familiar with RGB
  12996. color, pixel maps, pixel patterns, and other material introduced in the Color QuickDraw
  12997. chapter. You should also be familiar with the material in the Graphics Devices chapter,
  12998. since the Color Manager routines work on the device level.
  12999.  
  13000. Keep in mind that Color Manager routines are the intermediary between high-level
  13001. software such as Color QuickDraw, the Palette Manager, and the Color Picker, and the
  13002. lower-level video devices. The majority of applications will never need to use the
  13003. Color Manager routines directly.
  13004.  
  13005. Reader’s guide: The material in this chapter is largely for informational
  13006.                 purposes only, since Color QuickDraw, the Palette Manager,
  13007.                 and the other color Toolbox routines provide a detailed and
  13008.                 consistent way to add color to Macintosh programs.
  13009.  
  13010. _______________________________________________________________________________
  13011.  
  13012.  
  13013. æKY About…the…Color…Manager
  13014. æC »ABOUT THE COLOR MANAGER                                      ColorManager
  13015. _______________________________________________________________________________
  13016.  
  13017. The Color Manager is optimized to work with graphics hardware that utilizes a Color
  13018. Look-up Table (CLUT), a data structure that maps color indices, specified using
  13019. QuickDraw, into actual color values. The  exact color capabilities of the Macintosh
  13020. II depend on the particular video card used. There are three kinds of devices:
  13021.  
  13022.   •  CLUT devices contain hardware that converts an arbitrary pixel value
  13023.      stored in the frame buffer to some actual RGB video value, which is
  13024.      changeable. The pixel value could be the index to any of the colors
  13025.      in the current color set for the device, and the color set itself
  13026.      can be changed.
  13027.   •  Fixed devices also convert a pixel value to some actual RGB video
  13028.      value, but the hardware colors can’t be changed. The pixel value
  13029.      could be the index to any of the colors in the color set, but the
  13030.      color set itself always remains the same.
  13031.   •  Direct devices have a direct correlation between the value placed in
  13032.      the frame buffer and the color you see on the screen. The value placed
  13033.      in the frame buffer would produce the same color every time. Direct
  13034.      devices aren’t supported in the initial release of Color QuickDraw.
  13035.  
  13036. Applications that limit themselves to a small set of colors can use them simply and
  13037. easily from QuickDraw, with a minimum of overhead.  Color QuickDraw accesses the
  13038. Color Manager to obtain the best available color matches in the lookup table. Applications
  13039. such as color painting and animation programs, which need greater control over the
  13040. precise colors they use, can use the Palette Manager to allocate part of the color
  13041. table for their own exclusive use. The Palette Manager, described in a later chapter,
  13042. is useful for most applications that use shared color resources, imaging, or color
  13043. table animation. The Palette Manager is used whenever color is used for objects
  13044. within windows, while the Color Manager operates on the device level.
  13045.  
  13046. Note:  Palette Manager routines operate transparently across multiple
  13047.        screens, while Color Manager routines do not. Therefore, always
  13048.        use Palette Manager routines for applications that will run on
  13049.        multiple screens or in a multitasking environment.
  13050.  
  13051. The sections that follow describe how the Color Manager converts the RGB values
  13052. specified using Color QuickDraw into the actual colors available on a device. The
  13053. pixel value, specifying the number of bits per pixel, is set using the Control Panel.
  13054.  
  13055. _______________________________________________________________________________
  13056.  
  13057. »Graphics Devices
  13058.  
  13059. As with Color QuickDraw, the Color Manager accesses a particular graphics device
  13060. through a data structure known as a gDevice record. Each gDevice record stores information
  13061. about a particular graphics device; after this record is initialized, the device
  13062. itself is known to the Color Manager and QuickDraw as a gDevice. See the Graphics
  13063. Devices chapter for more details on gDevice format and on the routines that allow an
  13064. application to access a given device. Remember that a gDevice is a logical device,
  13065. which the software treats the same whether it is a video card, a display device, or
  13066. an offscreen pixel map.
  13067.  
  13068. _______________________________________________________________________________
  13069.  
  13070. »Color Table Format
  13071.  
  13072. The complete set of colors in use at a given time for a particular gDevice is summarized
  13073. in a color table record. Its format is as follows:
  13074.  
  13075. TYPE
  13076.   CTabHandle = ^CTabPtr;
  13077.   CTabPtr    = ^ColorTable;
  13078.   ColorTable = RECORD
  13079.                  ctSeed:   LONGINT;  {unique identifier from table}
  13080.                  ctFlags:  INTEGER;  {high bit is set for a gDevice, }
  13081.                                      { clear for a pixMap}
  13082.                  ctSize:   INTEGER;  {Number of entries in table-1}
  13083.                  ctTable:    cSpecArray
  13084.                END;
  13085.  
  13086. Field descriptions
  13087.  
  13088. ctSeed     The ctSeed field is similar to a version identifier number for
  13089.            a color table. If a color table is created by an application, it
  13090.            should call GetCTSeed to obtain this identifier. The ctSeed should
  13091.            be some unique number higher than minSeed, a predefined constant
  13092.            with a value of 1023. If a color table is created from a resource,
  13093.            its resource number will be used as the initial ctSeed. For 'CLUT'
  13094.            resource, the range of resource numbers should be 0–1023.
  13095.  
  13096. ctFlags    The ctFlags field is significant for gDevices only. It contains
  13097.            flags that describe the format of the ctTable. Currently, only
  13098.            the high bit is defined; all others are reserved. Color tables
  13099.            that are part of the gDevice structure always have this bit set.
  13100.            Color tables that are part of pixMaps have this bit clear. Each
  13101.            gDevice has its own pixMap, which has a color table.
  13102.  
  13103. ctSize     The ctSize field contains the number of entries in the color
  13104.            table minus one. All counts on color table entries are zero based.
  13105.  
  13106. ctTable    The ctTable field contains a cSpecArray, which is an array of
  13107.            ColorSpec entries. Notice that each entry in the color table is
  13108.            a ColorSpec, not simply an RGBColor. The type ColorSpec is
  13109.            composed of an integer value and an RGB color, as shown in the
  13110.            following specification. A color table may include a number of
  13111.            ColorSpec records.
  13112.  
  13113. TYPE
  13114.   cSpecArray = ARRAY [0..0] OF ColorSpec;
  13115.   ColorSpec  = RECORD
  13116.                  value : INTEGER;    {Color representation}
  13117.                  rgb   : RGBColor    {Color value}
  13118.                END;
  13119.   RGBColor   = RECORD
  13120.                  red   : INTEGER;    {Red component}
  13121.                  green : INTEGER;    {Green component}
  13122.                  blue  : INTEGER     {Blue component}
  13123.                END;
  13124.  
  13125. In gDevice color tables, the colorSpec.value field is reserved for use by the Color
  13126. Manager and Palette Manager. Their interpretation and values are different than the
  13127. color tables contained in pixMaps.
  13128.  
  13129. •••Refer to Figure 1.•••
  13130.  
  13131. Figure 1–Color Table Format
  13132.  
  13133. Note that the colorSpec.value field of the record is only word size (16 bits), even
  13134. though color index values (as returned by Color2Index) may be long words. The current
  13135. implementation of Color QuickDraw only supports 16 bits. The components in an RGBColor
  13136. are left-justified rather than right-justified in a word. Video drivers should respect
  13137. this convention and extract the appropriate number of bits from the high order side
  13138. of the component. For example, the Apple Graphics Card uses only the most significant
  13139. eight bits of each component of the RGBColor record.
  13140.  
  13141. _______________________________________________________________________________
  13142.  
  13143. »Inverse Tables
  13144.  
  13145. Reader’s guide: The material in this section is provided for informational
  13146.                 and debugging purposes, since most programs won’t need to
  13147.                 use inverse tables.
  13148.  
  13149. For normal drawing, Color QuickDraw takes all specifications as absolute RGB triples,
  13150. by means of the RGBColor record. Internally, these absolute specifications are converted
  13151. to the appropriate values to be written into the video card. For direct devices, the
  13152. RGB is separated into its red, green, and blue components, and each of these is
  13153. written to the video card. On CLUT and fixed devices, however, there isn’t always a
  13154. direct relationship between the specified RGB and the index value written into the
  13155. frame buffer; in fact, on CLUT devices, the best-match index value may change dynamically
  13156. as the colors available in the hardware are changed. On these types of devices, Color
  13157. QuickDraw uses the Color Manager to find the best matches among the colors currently
  13158. available.
  13159.  
  13160. The method used to determine the best available match can be specified by the application
  13161. or the system on a gDevice by gDevice basis. By default, on CLUT and fixed devices, a
  13162. special data structure called an inverse table is created. An inverse table is a
  13163. table arranged in such a manner that, given an arbitrary RGB color, the pixel value
  13164. can be very rapidly looked up.
  13165.  
  13166. In the default case, a certain number of the most significant bits of red, green, and
  13167. blue are extracted, then concatenated together to form an index into the inverse
  13168. table. At this location is the “best” match to the specified color. The number of
  13169. bits per color channel that are used to construct this index is known as the resolution
  13170. of the inverse table, and can be 3, 4, or 5 bits per channel. As the resolution of
  13171. the inverse table increases, the number of permutations of possible colors increases,
  13172. as does the size of the inverse table. Three-bit tables occupy 512 bytes, 4-bit
  13173. tables (the default) occupy 4K bytes, and 5-bit tables occupy 32K bytes.
  13174.  
  13175. A disadvantage of this method is that certain colors that are “close” together can
  13176. become hidden when they differ only in bits that weren’t used to construct the inverse
  13177. table index. For example, even if the color table were loaded with 256 levels of
  13178. gray, a 4-bit inverse table can only discriminate among 16 of the levels. To solve
  13179. this problem without having to use special-case sets of colors with hidden colors,
  13180. inverse tables carry additional information about how to find colors that differ only
  13181. in the less significant bits. As a result, when the Color2Index routine is called, it
  13182. can find the best match to the full 48-bit resolution available in a colorSpec. Since
  13183. examining the extra information takes time, certain parts of Color QuickDraw, notably
  13184. drawing in the arithmetic transfer modes, don’t use this information, and hence won’t
  13185. find the hidden colors.
  13186.  
  13187. In most cases, when setting colors using RGBForeColor and RGBBackColor, and when
  13188. using CopyBits to transfer pixMaps, inverse tables of four bits are sufficient. When
  13189. using arithmetic transfer modes with certain color tables that have closely-spaced
  13190. colors, the screen appearance may be improved by specifying inverse tables at 5-bit
  13191. resolution. Because the format of inverse tables is subject to change in the future,
  13192. or may not be present on certain devices, applications should not assume the structure
  13193. of the data.
  13194.  
  13195. The data in inverse tables remains valid as long as the color table from which it was
  13196. built remains unchanged. When a color table is modified, the inverse table must be
  13197. rebuilt, and the screen should be redrawn to take advantage of this new information.
  13198. Rather than being reconstructed when the color table is changed, the inverse table is
  13199. marked invalid, and is automatically rebuilt when next accessed.
  13200.  
  13201. Rather than testing each entry of the color table to see if it has changed, the
  13202. color-matching code compares the ctSeed of the current gDevice’s colorTable against
  13203. the iTabSeed of that gDevice’s inverse table. Each routine that modifies the colorTable
  13204. (with the exception of RestoreEntries) increments the ctSeed field of that colorTable.
  13205. If the ctSeed and the iTabSeed don’t match, the inverse table is reconstructed for
  13206. that gDevice.
  13207.  
  13208. Note:  Under normal circumstances, all invalidations are posted and serviced
  13209.        transparently to the application. This method of invalidation is the
  13210.        same as that used to invalidate expanded patterns and cursors elsewhere
  13211.        in Color QuickDraw.
  13212.  
  13213. In certain cases, it may be useful to override the inverse table matching code with
  13214. custom routines that have special matching rules. See the section titled
  13215. “Custom Search and Complement Procedures” for more details.
  13216.  
  13217. The Color Manager performs a color table look-up in the following manner:
  13218.  
  13219.   1.  Builds a table of all possible RGB values;
  13220.   2.  For each position in the table, attempts to get the closest match;
  13221.   3.  Reduces the resolution of the lookup to four bits when constructing
  13222.       the table, but later adds information to get a better resolution.
  13223.  
  13224. The Color Manager performs this table-building sequence whenever colors are requested
  13225. by Color QuickDraw, the Color Picker, or the Palette Manager. This isn’t the only
  13226. color matching method available; a custom search procedure, for example, may not have
  13227. an inverse table. (See the section titled “Custom Search and Complement Procedures”
  13228. for more information.) However, inverse tables are the default method for color
  13229. matching.
  13230.  
  13231. When using an inverse table, the table is indexed by concatenating together the
  13232. high-order bits of the three desired color components; iTabRes tells how many bits of
  13233. each component are significant. The format of an inverse table is shown below:
  13234.  
  13235. TYPE
  13236.   ITabHandle = ^ITabPtr;
  13237.   ITabPtr    = ^ITab;
  13238.   ITab       = RECORD
  13239.                  iTabSeed:  LONGINT;    {copy of color table seed}
  13240.                  iTabRes:   INTEGER;    {resolution of table}
  13241.                  iTTable:   ARRAY[0..0] OF SignedByte {byte color }
  13242.                                         { table index values}
  13243.                END;
  13244.  
  13245. The size of an index table in bytes is 2^3*iTabRes. The table below shows a sample
  13246. index table:
  13247.  
  13248. resolution        RGB color      inverse-table     size
  13249.                                  index
  13250.     4-bit         red=$1234,
  13251.                   green=$5678,
  13252.                   blue=$9ABC     $0159             2^12 = 4K bytes
  13253.  
  13254.     5-bit         red=$1234,
  13255.                   green=$5678,
  13256.                   blue=$9ABC     $0953             2^15 = 32K bytes
  13257.  
  13258. MakeITable only supports 3-bit, 4-bit, and 5-bit resolution. Five bits is the maximum
  13259. possible resolution, since the indices into a 6-bit table would have to be 18 bits
  13260. long, more than a full word.
  13261.  
  13262. _______________________________________________________________________________
  13263.  
  13264.  
  13265. æKY Using…the…Color…Manager
  13266. æC »USING THE COLOR MANAGER                                      ColorManager
  13267. _______________________________________________________________________________
  13268.  
  13269. In the simplest cases, use of the Color Manager is transparent when invoking the new
  13270. Color QuickDraw routines. Using RGBForeColor and RGBBackColor, the program requests
  13271. an RGB color for either the foreground or background. For instance, the following
  13272. code requests an RGB color of red and sets it in the cGrafPort:
  13273.  
  13274.   myColor.red:=$FFFF;
  13275.   myColor.green:=0;
  13276.   myColor.blue:=0;
  13277.   RGBForeColor(myColor); {set pen red}
  13278.   FrameRect(myRect); {draw in red}
  13279.  
  13280. Internally the Color Manager finds the best match to a color in TheGdevice’s current
  13281. color table, and sets up the current cGrafPort to draw in this color. At this point,
  13282. drawing operations can proceed using the selected colors.
  13283.  
  13284. The Color Manager routines described in this chapter are designed to operate on a
  13285. single gDevice. The Palette Manager can perform most of these operations across
  13286. multiple gDevices. Since the Palette Manager provides more general and portable
  13287. functionality, applications should use Palette Manager routines whenever possible.
  13288.  
  13289. The SetEntries routine is used to change any part of or all of the entries in a
  13290. device’s hardware Color Look-Up Table. The SaveEntries and RestoreEntries routines
  13291. can make temporary changes to the color table under very specialized circumstances
  13292. (such as a color selection dialog within an application). These routines aren’t
  13293. needed under normal application circumstances.
  13294.  
  13295. SaveEntries allows any combination of colorSpecs to be copied into a special colorTable.
  13296. RestoreEntries replaces the table created by SaveEntries into the graphics device.
  13297. Unlike SetEntries, these routines don’t perform invalidations of the device’s colorTable,
  13298. so they avoid causing invalidations of cached data structures. When these routines
  13299. are used, the application must take responsibility for rebuilding and restoring
  13300. auxiliary structures as necessary.
  13301.  
  13302. By convention, when using SetEntries or RestoreEntries, white should be located at
  13303. color table position 0, and black should be stored in the last color table position
  13304. available, whether it is 1, 3, 15, or 255. The Palette Manager also enforces this
  13305. convention.
  13306.  
  13307. For precise control over color, or for dedicated color table entries, the Color
  13308. Manager routines maintain special information in device color tables. Using ProtectEntry
  13309. and ReserveEntry, an entry may be protected, which prevents SetEntries from further
  13310. changing the entry, or reserved, which makes the entry unavailable to be matched by
  13311. RGBForeColor and RGBBackColor. Routines that change the device table (SetEntries,
  13312. ProtectEntry, and ReserveEntry, but not RestoreEntries) will perform the appropriate
  13313. invalidations of QuickDraw data structures. The application must then redraw where
  13314. necessary.
  13315.  
  13316. To inquire if a color exists in a color table, use RealColor. This tells whether an
  13317. arbitrary color actually exists in the table for that gDevice.
  13318.  
  13319. Color2Index returns the index in the current device’s colorTable that is the best
  13320. match to the requested color. Index2Color performs the opposite function—it returns
  13321. the RGB of a particular index value. These routines can be useful when making copies
  13322. of the screen frame buffer. InvertColor finds the complement of the provided color.
  13323. GetSubTable performs a group Color2Index on a colorTable.
  13324.  
  13325. _______________________________________________________________________________
  13326.  
  13327.  
  13328. æKY Color…Manager…Routines
  13329. æC »COLOR MANAGER ROUTINES                                       ColorManager
  13330. _______________________________________________________________________________
  13331.  
  13332. The routines used for color drawing are covered in the chapter “Color
  13333. QuickDraw”. The Color Manager includes routines for color conversion, color table
  13334. management, and error handling.
  13335.  
  13336. _______________________________________________________________________________
  13337.  
  13338. »Color Conversion
  13339.  
  13340. FUNCTION Color2Index (rgb: RGBColor): LONGINT;
  13341.  
  13342. The Color2Index routine finds the best available approximation to a given absolute
  13343. color, using the list of search procedures in the current device record. It returns a
  13344. longint, which is a pixel value padded with zeros in the high word. Since the colorSpec.value
  13345. field is only a word, the result returned from Color2Index must be truncated to fit
  13346. into a colorSpec. In pixMaps the
  13347. .value is the low-order word of this index.
  13348.  
  13349. Color2Index shouldn’t be called from a custom search procedure.
  13350.  
  13351. PROCEDURE Index2Color (index: LONGINT; VAR rgb: RGBColor);
  13352.  
  13353. The Index2Color routine finds the RGB color corresponding to a given color table
  13354. index. The desired pixel value is passed and the corresponding RGB value is returned
  13355. in RGB. The routine takes a longint, which should be a pixel value padded with zeros
  13356. in the high word (normally the compiler does this automatically). Normally, the RGB
  13357. from the current device color table corresponding to the index is returned as the
  13358. RGBColor. Notice that this is not necessarily the same color that was originally
  13359. requested via RGBForeColor, RGBBackColor, SetCPixel, or Color2Index. This RGB is read
  13360. from the current gDevice color table.
  13361.  
  13362. PROCEDURE InvertColor (VAR theColor: RGBColor);
  13363.  
  13364. The InvertColor routine finds the complement of an absolute color, using the list of
  13365. complement procedures in the current device record. The default complement procedure
  13366. uses the 1’s complement of each component of the requested color.
  13367.  
  13368. FUNCTION RealColor (color: RGBColor) : BOOLEAN;
  13369.  
  13370. The RealColor routine tells whether a given absolute color actually exists in the
  13371. current device’s color table. This decision is based on the current resolution of the
  13372. inverse table. For example, if the current iTabRes is four, RealColor returns TRUE if
  13373. there exists a color that exactly matches the top four bits of red, green, and blue.
  13374.  
  13375. PROCEDURE GetSubTable (myColors: CTabHandle; iTabRes:INTEGER;
  13376.                        targetTbl: CTabHandle);
  13377.  
  13378. The GetSubTable routine takes a ColorTable pointed at by myColors, and maps each RGB
  13379. value into its nearest available match for each target table. These best matches are
  13380. returned in the colorSpec.value fields of myColors. The values returned are best
  13381. matches to the RGBColor in targetTbl and the returned indices are indices into targetTbl.
  13382. Best matches are calculated using Color2Index and all applicable rules apply. A
  13383. temporary inverse table is built, and then discarded. ITabRes controls the resolution
  13384. of the iTable that is built. If targetTbl is NIL, then the current device’s color
  13385. table is used, and the
  13386. device’s inverse table is used rather than building a new one. To provide a different
  13387. resolution than the current inverse table, provide an explicit targetTbl parameter;
  13388. don’t pass a NIL parameter.
  13389.  
  13390. Warning:  Depending on the requested resolution, building the inverse table
  13391.           can require large amounts of temporary space in the application
  13392.           heap:  twice the size of the table itself, plus a fixed overhead
  13393.           for each inverse table resolution of 3–15K bytes.
  13394.  
  13395. PROCEDURE MakeITable (colorTab: CTabHandle; inverseTab: ITabHandle;
  13396.                       res: INTEGER);
  13397.  
  13398. The MakeITable routine generates an inverse table based on the current contents of
  13399. the color table pointed to by CTabHandle, with a resolution of res bits per channel.
  13400. Reserved color table pixel values are not included in the resultant color table.
  13401. MakeITable tests its input parameters and will return an error in QDError if the
  13402. resolution is less than three or greater than five. Passing a NIL parameter to CTabHandle
  13403. or ITabHandle substitutes an appropriate handle from the current gDevice, while
  13404. passing 0 for res substitutes the current gDevice’s preferred table resolution. These
  13405. defaults can be used in any combination with explicit values, or with NIL parameters.
  13406.  
  13407. This routine allows maximum precision in matching colors, even if colors in the color
  13408. table differ by less than the resolution of the inverse table. Five-bit inverse
  13409. tables are not needed when drawing in normal QuickDraw modes. However, the new QuickDraw
  13410. transfer modes (add, subtract, blend, etc.) may require a
  13411. 5-bit inverse table for best results with certain color tables. MakeITable returns a
  13412. QDError if the destination inverse table memory cannot be allocated. The 'mitq'
  13413. resource governs how much memory is allocated for temporary internal structures; this
  13414. resource type is for internal use only.
  13415.  
  13416. Warning:  Depending on the requested resolution, building the inverse table
  13417.           can require large amounts of temporary space in the application
  13418.           heap:  twice the size of the table itself, plus a fixed overhead
  13419.           for each inverse table resolution of 3–15K bytes.
  13420.  
  13421. _______________________________________________________________________________
  13422.  
  13423. »Color Table Management
  13424.  
  13425. FUNCTION GetCTSeed : LONGINT;
  13426.  
  13427. The GetCTSeed function returns a unique seed value that can be used in the ctSeed
  13428. field of a color table created by an application. This seed value guarantees that the
  13429. color table will be recognized as distinct from the destination, and that color table
  13430. translation will be performed properly. The return value will be greater than the
  13431. value stored in minSeed.
  13432.  
  13433. PROCEDURE ProtectEntry (index: INTEGER; protect: BOOLEAN);
  13434.  
  13435. The ProtectEntry procedure protects or removes protection from an entry in the current
  13436. device’s color table, depending on the value of the protect parameter.  A protected
  13437. entry can’t be changed by other clients.  It returns a protection error if it attempts
  13438. to protect an already protected entry. However, it can remove protection from any
  13439. entry.
  13440.  
  13441. PROCEDURE ReserveEntry (index: INTEGER; reserve: BOOLEAN);
  13442.  
  13443. The ReserveEntry procedure reserves or dereserves an entry in the current color
  13444. table, depending on the value of the reserve parameter.  A reserved entry cannot be
  13445. matched by another client’s search procedure, and will never be returned to another
  13446. client by Color2Index or other routines that depend on it
  13447. (such as RGBForeColor, RGBBackColor, SetCPixel, and so forth).  You could use this
  13448. routine to selectively protect a color for color table animation.
  13449.  
  13450. ReserveEntry copies the low byte of gdID into the low byte of ColorSpec.value when
  13451. reserving an entry, and leaves the high byte alone. It acts like a selective protection,
  13452. and does not allow any changes if the current gdID is different than the one in the
  13453. colorSpec.value field of the reserved entry. If a requested match is already reserved,
  13454. ReserveEntry returns a protection error. Any entry can be dereserved.
  13455.  
  13456. PROCEDURE  SetEntries(start, count: INTEGER; aTable: CSpecArray);
  13457.  
  13458. The SetEntries procedure sets a group of color table entries for the current gDevice,
  13459. starting at a given position for the specified number of entries. The pointer aTable
  13460. points into a cSpecArray, not into a color table.  The colorSpec.value field of the
  13461. entries must be in the logical range for the target card’s assigned pixel depth.
  13462. Thus, with a 4-bit pixel size, the colorSpec.value fields should be in the range 1 to
  13463. 15. With an 8-bit pixel size the range is 0 to 255.  Note that all values are zero-based;
  13464. for example, to set three entries, pass two in the count parameter.
  13465.  
  13466. Note:  Palette Manager routines should be used instead of the SetEntries
  13467.        routine for applications that will run in a multiscreen or
  13468.        multitasking environment.
  13469.  
  13470. The SetEntries positional information works in logical space, rather than in the
  13471. actual memory space used by the hardware. Requesting a change at position four in the
  13472. color table may not modify color table entry four in the hardware, but it does correctly
  13473. change the color on the screen for any pixels with a value of four in the video card.
  13474. The SetEntries mode characterized by a start position and a length is called sequence
  13475. mode. In this case, new colors are sequentially loaded into the hardware in the same
  13476. order as the aTable, the clientID fields for changed entries are copied from the
  13477. current device’s gdID field, and the colorSpec.value fields are ignored.
  13478.  
  13479. The other SetEntries mode is called index mode. It allows the cSpecArray to specify
  13480. where the data will be installed on an entry-by-entry basis. To use this mode, pass
  13481. –1 for the start position, with a valid count and a pointer to the cSpecArray. Each
  13482. entry is installed into the color table at the position specified by the colorSpec.value
  13483. field of each entry in the cSpecArray. In the current device’s color table, all
  13484. changed entries’ colorSpec.value fields are assigned the gdID value.
  13485.  
  13486. When color table entries are changed, all cached fonts are invalidated, and the seed
  13487. number is changed so that the next drawing operation will rebuild the inverse table.
  13488. If any of the requested entries are protected or out of range, a protection error is
  13489. returned, and nothing happens. If a requested entry is reserved, it can only be
  13490. changed if the current gdID matches the low byte of the intended ColorSpec.value
  13491. field.
  13492.  
  13493. PROCEDURE SaveEntries (srcTable: CTabHandle; ResultTable: CTabHandle;
  13494.                        VAR  selection: ReqListRec);
  13495.  
  13496. SaveEntries saves a selection of entries from srcTable into resultTable. The entries
  13497. to be set are enumerated in the selection parameter, which uses the ReqListRec data
  13498. structure shown below. (These values are offsets into colorTable, not the contents of
  13499. the colorSpec.value field.)
  13500.  
  13501. TYPE
  13502.   ReqListRec = RECORD
  13503.                  reqLSize:  INTEGER;                 {request list size –1}
  13504.                  reqLData:  ARRAY [0..0] of INTEGER  {request list data}
  13505.                END;
  13506.  
  13507. If an entry is not present in srcTable, then that position of the requestList is set
  13508. to colReqErr, and that position of resultTable has random values returned. If one or
  13509. more entries are not found, then an error code is posted to QDError; however, for
  13510. every entry in selection which is not colReqErr, the values in resultTable are valid.
  13511. Note that srcTable and selection are assumed to have the same number of entries.
  13512.  
  13513. SaveEntries optionally allows NIL as its source color table parameter. If NIL is
  13514. used, the current device’s color table is used as the source. The output of SaveEntries
  13515. is the same as the input for RestoreEntries, except for the order.
  13516.  
  13517. PROCEDURE RestoreEntries (srcTable:CTabHandle;DstTable:CTabHandle;
  13518.                           VAR selection:ReqListRec);
  13519.  
  13520. RestoreEntries sets a selection of entries from srcTable into dstTable, but doesn’t
  13521. rebuild the inverse table. The dstTable entries to be set are enumerated in the
  13522. selection parameter, which uses the ReqListRec data structure shown in the SetEntries
  13523. routine description. (These values are offsets into the srcTable, not the contents of
  13524. the colorSpec.value field.)
  13525.  
  13526. If a request is beyond the end of the dstTable, that position of the requestList is
  13527. set to colReqErr, and an error is returned. Note that srcTable and selection are
  13528. assumed to have the same number of entries.
  13529.  
  13530. If dstTbl is NIL, or points to the device color table, the current device’s color
  13531. table is updated, and the hardware is updated to these new colors. The seed is not
  13532. changed, so no invalidation occurs (this may cause RGBForeColor to act strangely).
  13533. This routine ignores protection and reservation of color table entries.
  13534.  
  13535. Generally, the Palette Manager is used to give an application its own set of colors;
  13536. use of RestoreEntries should be limited to special-purpose applications. RestoreEntries
  13537. allows you to change the colorTable without changing the ctSeed for the affected
  13538. colorTable. You can execute the application code and then use RestoreEntries to put
  13539. the original colors back in. However, in some cases things in the background may
  13540. appear in the wrong colors, since they were never redrawn. To avoid this, the application
  13541. must build its own new inverse table and redraw the background. If RestoreEntries
  13542. were then used, the ctSeed would have to be explicitly changed to clean up correctly.
  13543.  
  13544. _______________________________________________________________________________
  13545.  
  13546. »Error Handling
  13547.  
  13548. FUNCTION QDError: INTEGER;
  13549.  
  13550. The QDError routine returns the error result from the last QuickDraw or Color Manager
  13551. call.  This routine is even more useful with 32-Bit QuickDraw.  It is important that
  13552. you check for errors after every QuickDraw call.  For more information, see the
  13553. 32-Bit QuickDraw documentation.
  13554.  
  13555. _______________________________________________________________________________
  13556.  
  13557.  
  13558. æKY Custom…Search…and…Complement…Functions
  13559. æC »CUSTOM SEARCH AND COMPLEMENT FUNCTIONS                       ColorManager
  13560. _______________________________________________________________________________
  13561.  
  13562. The custom search function allows an application to override the inverse table matching
  13563. code. The desired color is specified in the RGBColor field of a ColorSpec record and
  13564. passed via a pointer on the stack; the procedure returns the corresponding pixel
  13565. value in the ColorSpec.value field.
  13566.  
  13567. A custom search routine can provide its own matching rules. For instance, you might
  13568. want to map all levels of green to a single green on a monitor. To do this, you could
  13569. write and install a custom search procedure that is passed the RGB under question by
  13570. the Color Manager. It can then analyze the color, and if it decides to act on this
  13571. color, it can return the index of the desired shade of green. Otherwise, it can pass
  13572. the color back to the Color Manager for matching, using the normal inverse table
  13573. routine.
  13574.  
  13575. Many applications can share the same graphics device, each with its own custom search
  13576. procedure.  The procedures are chain elements in a linked list beginning in the
  13577. gdSearchProc field of the gDevice port:
  13578.  
  13579. TYPE
  13580.   SProcHndl = ^SProcPtr;
  13581.   SProcPtr  = ^SProcRec;;
  13582.   SProcRec  = RECORD
  13583.                 nxtSrch:   SProcHndl;  {handle to next sProcRec}
  13584.                 srchProc:  ProcPtr     {pointer to search procedure}
  13585.               END;
  13586.  
  13587. Any number of search procedures can be installed in a linked list, each element of
  13588. which will be called sequentially by the Color Manager, and given the chance to act
  13589. or pass on the color. Since each device is a shared resource, a simple method (the
  13590. gdID) is provided to identify the caller to the search procedures, as well as routines
  13591. to add and delete custom procedures from the linked list.
  13592.  
  13593. The interface is as follows:
  13594.  
  13595. FUNCTION SearchProc (rgb: RGBColor; VAR position: LONGINT): BOOLEAN;
  13596.  
  13597. When attempting to approximate a color, the Color Manager calls each search procedure
  13598. in the list until the boolean value returns as TRUE.  The index value of the closest
  13599. match is returned by the position parameter.  If no search procedure installed in the
  13600. linked list returns TRUE, the Color Manager calls the default search procedure.
  13601.  
  13602. The application can also supply a custom complement procedure to find the complement
  13603. of a specified color. Complement procedures work the same as search procedures, and
  13604. are kept in a list beginning in the gDevice port’s gdCompProc field.
  13605.  
  13606. TYPE
  13607.   CProcHndl = ^CProcPtr;
  13608.   CProcPtr  = ^CProcRec;
  13609.   CProcRec  = RECORD
  13610.                 nxtComp:   CProcHandle;  {pointer to next CProcRec}
  13611.                 compProc:  ProcPtr       {pointer to complement procedure}
  13612.               END;
  13613.  
  13614. The default complement procedure simply uses the 1’s complement of the RGB color
  13615. components before looking them up in the inverse table. The interface is as follows:
  13616.  
  13617. FUNCTION CompProc (VAR rgb: RGBColor) : BOOLEAN;
  13618.  
  13619. _______________________________________________________________________________
  13620.  
  13621. »Operations on Search and Complement Functions
  13622.  
  13623. PROCEDURE AddSearch (searchProc: ProcPtr);
  13624. PROCEDURE AddComp   (compProc: ProcPtr);
  13625.  
  13626. The AddSearch and AddComp routines add a procedure to the head of the current device
  13627. record’s list of search or complement procedures. These routines allocate an SProcRec
  13628. or CProcRec.
  13629.  
  13630. PROCEDURE DelSearch (searchProc: ProcPtr);
  13631. PROCEDURE DelComp   (compProc: ProcPtr);
  13632.  
  13633. The DelSearch and DelComp procedures remove a custom search or complement procedure
  13634. from the current device record’s list of search or complement procedures. These
  13635. routines dispose of the chain element, but do nothing to the procPtr.
  13636.  
  13637. PROCEDURE SetClientID (id: INTEGER);
  13638.  
  13639. The SetClientID procedure sets the gdID field in the current device record to identify
  13640. this client program to its search and complement procedures.
  13641.  
  13642. _______________________________________________________________________________
  13643.  
  13644.  
  13645. æKY Summary…of…the…Color…Manager
  13646. æC »SUMMARY OF THE COLOR MANAGER                                 ColorManager
  13647. _______________________________________________________________________________
  13648.  
  13649. Constants
  13650.  
  13651. CONST
  13652.   minSeed = 1023;    {minimum seed value for ctSeed}
  13653.  
  13654. _______________________________________________________________________________
  13655.  
  13656. Data Types
  13657.  
  13658. TYPE
  13659.   ITabHandle = ^ITabPtr;
  13660.   ITabPtr    = ^ITab;
  13661.   ITab       = RECORD
  13662.                  iTabSeed:  LONGINT;    {copy of color table seed}
  13663.                  iTabRes:   INTEGER;    {resolution of table}
  13664.                  iTTable:   ARRAY[0..0] OF SignedByte {byte color }
  13665.                                         { table index values}
  13666.                END;
  13667.  
  13668.   SProcHndl = ^SProcPtr;
  13669.   SProcPtr  = ^SProcRec;;
  13670.   SProcRec  = RECORD
  13671.                 nxtSrch:   SProcHndl;  {handle to next sProcRec}
  13672.                 srchProc:  ProcPtr     {pointer to search procedure}
  13673.               END;
  13674.  
  13675.   CProcHndl = ^CProcPtr;
  13676.   CProcPtr  = ^CProcRec;
  13677.   CProcRec  = RECORD
  13678.                 nxtComp:   CProcHandle;  {pointer to next CProcRec}
  13679.                 compProc:  ProcPtr       {pointer to complement procedure}
  13680.               END;
  13681.  
  13682.   ReqListRec = RECORD
  13683.                  reqLSize:  INTEGER;                 {request list size –1}
  13684.                  reqLData:  ARRAY [0..0] of INTEGER  {request list data}
  13685.                END;
  13686.  
  13687. _______________________________________________________________________________
  13688.  
  13689. Routines
  13690.  
  13691. Color Conversion
  13692.  
  13693. FUNCTION  Color2Index  (VAR rgb: RGBColor): LONGINT;
  13694. PROCEDURE Index2Color  (index: LONGINT; VAR rgb: RGBColor);
  13695. PROCEDURE InvertColor  (VAR theColor: RGBColor);
  13696. FUNCTION  RealColor    (color: RGBColor) : BOOLEAN;
  13697. PROCEDURE GetSubTable  (myColors: CTabHandle; iTabRes: INTEGER;
  13698.                         targetTbl:CTabHandle);
  13699. PROCEDURE MakeITable   (colorTab: CTabHandle; inverseTab: ITabHandle;
  13700.                         res: INTEGER);
  13701.  
  13702. Color Table Management
  13703.  
  13704. FUNCTION  GetCTSeed: LONGINT;
  13705. PROCEDURE ProtectEntry    (index: INTEGER; protect: BOOLEAN);
  13706. PROCEDURE ReserveEntry    (index: INTEGER; reserve: BOOLEAN);
  13707. PROCEDURE SetEntries      (start, count: INTEGER; aTable: cSpecArray);
  13708. PROCEDURE RestoreEntries  (srcTable:CTabHandle;dstTable:CTabHandle;
  13709.                            VAR selection:ReqListRec);
  13710. PROCEDURE SaveEntries     (srcTable:CTabHandle;resultTable:CTabHandle; VAR selection:ReqListRec)
  13711.  
  13712. Operations on Search and Complement Functions
  13713.  
  13714. PROCEDURE AddSearch    (searchProc: ProcPtr);
  13715. PROCEDURE AddComp      (compProc: ProcPtr);
  13716. PROCEDURE DelSearch    (searchProc: ProcPtr);
  13717. PROCEDURE DelComp      (compProc: ProcPtr);
  13718. PROCEDURE SetClientID  (id: INTEGER);
  13719.  
  13720. Error Handling
  13721.  
  13722. FUNCTION QDError: INTEGER;
  13723.  
  13724. _______________________________________________________________________________
  13725.  
  13726. Assembly Language Information
  13727.  
  13728. Constants
  13729.  
  13730. minSeed    EQU    1023  ;minimum ctSeed value
  13731.  
  13732. ITab structure
  13733.  
  13734. iTabSeed   EQU    $0    ;[long] ID of owning color table
  13735. iTabRes    EQU    $4    ;[word] client ID
  13736. iTTable    EQU    $6    ;table of indices starts here
  13737.                         ;in this version, entries are BYTE
  13738.  
  13739. SProcRec structure
  13740.  
  13741. nxtSrch    EQU    $0    ;[pointer] link to next proc
  13742. srchProc   EQU    $4    ;[pointer] pointer to routine
  13743.  
  13744. CProcRec structure
  13745.  
  13746. nxtComp    EQU    $0    ;[pointer] link to next proc
  13747. compProc   EQU    $4    ;[pointer] pointer to routine
  13748.  
  13749. Request list structure
  13750.  
  13751. reqLSize   EQU    0    ;[word] request list size –1
  13752. reqLData   EQU    2    ;[word] request list data
  13753.  
  13754. Further Reference:
  13755. _______________________________________________________________________________
  13756. Color QuickDraw
  13757. Graphics Devices
  13758. Palette Manager
  13759. Color Picker Package
  13760. 32-Bit QuickDraw Documentation
  13761.  
  13762. æKY ColorPickerPackage
  13763. æC 
  13764. _______________________________________________________________________________
  13765.  
  13766. COLOR PICKER PACKAGE
  13767. _______________________________________________________________________________
  13768.  
  13769. About…the…Color…Picker…Vol…VI…Chapter
  13770. About…the…Color…Picker…Vol…VI…Package
  13771. Color…Models
  13772.     The…RGB…Model
  13773.     The…CMYK…Model
  13774.     The…HLS…and…HSV…Models
  13775.     Color…Models…in…the…Dialog…Box
  13776. Using…the…Color…Picker…Package…Vol…VI
  13777.     Presenting…the…Dialog…Box
  13778.     Conversion…Facilities…Vol…VI
  13779. Color…Picker…Routines
  13780.     Displaying…the…Color…Picker…Dialog…Box
  13781.     Converting…Between…Color…Models
  13782.     Converting…Between…SmallFract…and…Fixed…Values
  13783. Summary…of…the…Color…Picker…Package…Vol…VI
  13784.     Color…Picker…Package…Constants
  13785.     Color…Picker…Package…Data…Types
  13786.     Color…Picker…Package…Routines…Vol…VI
  13787.     Assembly…Language…Information…for…Color…Picker…Package
  13788.  
  13789. About…The…ColorPickerPackage…Chapter
  13790. The…Color…Picker…Package
  13791. The…Color…Picker…Dialog…Box
  13792. Color…Picker…Package…Routines
  13793. Conversion…Facilities
  13794. Summary…of…the…Color…Picker…Package
  13795.  
  13796. _______________________________________________________________________________
  13797.  
  13798.  
  13799.  
  13800. æKY About…the…Color…Picker…Chapter…Vol…VI
  13801. æC »ABOUT THIS CHAPTER                                                Color Picker Package
  13802. _______________________________________________________________________________
  13803.  
  13804. This chapter describes the Color Picker Package, a utility with which
  13805. applications can offer users a standard dialog box for choosing a color. You
  13806. should be familiar with the material in the Graphics Overview chapter in this
  13807. volume, especially the discussion of direct and indexed video devices. Effective
  13808. use of the Color Picker will also require familiarity with Color QuickDraw,
  13809. described in Volume V of Inside Macintosh, and in this volume. 
  13810.  
  13811. This chapter supersedes the description of the Color Picker in Volume V.
  13812.  
  13813. You need to read this chapter if your application uses the color system
  13814. introduced with Color QuickDraw (rather than the 8-color system available with
  13815. the original QuickDraw), and you need to solicit color choices from your users.
  13816. If your application limits user selection to a specific list of colors, you may
  13817. need to construct your own dialog box for color selection using Palette Manager
  13818. routines, as the Color Picker allows the user to choose colors from the entire
  13819. range available with Color QuickDraw’s 48-bit RGB values.
  13820.  
  13821. _______________________________________________________________________________
  13822.  
  13823. æKY About…the…Color…Picker…Package…Vol…VI
  13824. æC »ABOUT THE COLOR PICKER PACKAGE                                    Color Picker Package
  13825. _______________________________________________________________________________
  13826.  
  13827. The Color Picker Package provides you with a standard way of soliciting a color
  13828. choice from the user. When an application calls the Color Picker’s GetColor
  13829. function, the Color Picker presents its dialog box to the user, as shown in
  13830. Figure 17-1. 
  13831.  
  13832. When the user is satisfied with a chosen color and clicks the OK button,
  13833. GetColor returns that color to your application as an RGB value. 
  13834.  
  13835. ø 17.1  The Color Picker dialog box
  13836.  
  13837. The Color Picker also has utility routines for converting between RGB values and
  13838. several other color systems, and for converting between the integers Color
  13839. QuickDraw uses for RGB colors and the SmallFract values the Color Picker uses
  13840. with alternate color models.
  13841.  
  13842. This chapter describes the color models the Color Picker works with, and how you
  13843. set up and present the dialog box to users.
  13844.  
  13845. _______________________________________________________________________________
  13846.  
  13847. æKY Color…Models
  13848. æC »COLOR MODELS                                                      Color Picker Package
  13849. _______________________________________________________________________________
  13850.  
  13851. Both QuickDraw and standard video monitors work with a red, green, blue (RGB)
  13852. color model, but in graphic arts and design other color models, such as HLS 
  13853. (hue, lightness, saturation) or HSV (hue, saturation, value) are used, and in
  13854. printing the CMYK (cyan, magenta, yellow, and black) model predominates. Great
  13855. books have been written about color; this section presents a quick survey of the
  13856. models with which the Color Picker works.
  13857.  
  13858. _______________________________________________________________________________
  13859.  
  13860. æKY The…RGB…Model
  13861. æC »The RGB Model                                                     Color Picker Package
  13862. _______________________________________________________________________________
  13863.  
  13864. In the RGB model, the three colors are additive. The more of each color you add
  13865. the closer the resulting color is to white. This is the way light-produced
  13866. colors work; turning on the red, green, and blue phosphors of a television
  13867. screen produces white, as does shining lights of red, green, and blue upon a
  13868. stage. 
  13869.  
  13870. The QuickDraw data structure for an RGBColor record is
  13871.  
  13872.   RGBColor = RECORD
  13873.   red:     Integer;  {red component}
  13874.   green:   Integer;  {green component}
  13875.   blue:    Integer   {blue component}
  13876.   END;
  13877.  
  13878. The frontispiece of Volume V of Inside Macintosh shows a color cube that
  13879. represents the values possible in an RGB system. Figure 17-2 is a
  13880. black-and-white representation of that cube.
  13881.  
  13882.  
  13883.     
  13884. ø 17.2  The RGB Color Cube
  13885.  
  13886. Starting at one corner, with zero values for each color, is black. Increasing
  13887. any one of the values produces shades of that color, increasing its saturation.
  13888. Increasing all three values equally generates a diagonal line across the cube
  13889. toward full value (65,535) for each, which is white. Values on that diagonal are
  13890. shades of gray; values off the line in any direction are colors. For example,
  13891. pink in the RGB model would be full red with some equal amount of green and
  13892. blue, in effect moving from the black corner of the color cube up along the edge
  13893. to full red, then traversing a diagonal across the top face from red toward
  13894. white. 
  13895.  
  13896.     
  13897. ø 17.3  Getting to pink
  13898.  
  13899. _______________________________________________________________________________
  13900.  
  13901. æKY The…CMYK…Model
  13902. æC »The CMYK Model                                                    Color Picker Package
  13903. _______________________________________________________________________________
  13904.  
  13905. In the CMYK model, which is used by the print world, the three colors and black
  13906. are subtractive: increasing values moves the result closer to black. This is
  13907. intuitive for printing, which is usually done on white paper—to get white, don’t
  13908. print anything. In theory, black could be achieved by mixing full values of
  13909. cyan, magenta, and yellow, but purity in chemicals is more problematic than with
  13910. light, and four-color print processes use black as well. The Color Picker’s
  13911. CMYColor data structure defines only the three colors. It uses SmallFract
  13912. values, which are the fractional part of Fixed values, as described in Color
  13913. Picker Conversion Facilities.
  13914.  
  13915.   CMYColor  = RECORD
  13916.   cyan:     SmallFract;
  13917.   magenta:  SmallFract;
  13918.   yellow:   SmallFract
  13919.   END;
  13920.  
  13921.  Note that cyan, magenta, and yellow are complements of red, green, and blue. 
  13922.  
  13923. ø 17.4  CMY on the color cube
  13924.  
  13925. _______________________________________________________________________________
  13926.  
  13927. æKY The…HLS…and…HSV…Models
  13928. æC »The HLS and HSV Models                                            Color Picker Package
  13929. _______________________________________________________________________________
  13930.  
  13931. The components of the HLS and HSV models are not three diverse colors, as in RGB
  13932. and CMY. The HLS and HSV models separate color, or hue, from brightness and
  13933. saturation. 
  13934.  
  13935. Brightness is a measure of how much black is in a color, saturation is a measure
  13936. of how much white it contains. Hue is indicated by an arbitrary assignment of
  13937. numbers to colors. The amount of that hue is indicated by a saturation value,
  13938. and the brightness of the color is a third value. The best representation for
  13939. such a system is an inverted cone, in which hues vary around the perimeter,
  13940. where they are most highly saturated, and brightness increases from the tip of
  13941. the cone to the disk. The gray line from black to white begins at the bottom-tip
  13942. and runs up through the cone to the center of the disk. 
  13943.       
  13944. ø 17.5  The HLS/HSV color cone
  13945.  
  13946. This is the model portrayed in the Color Picker’s dialog box. The disk is shown
  13947. full face, the hues are at their most saturated around the rim, and the
  13948. brightness line down the cone is controlled by the scroll bar.
  13949.  
  13950. In the Color Picker’s color wheel the value for pure red is 0, pure green is
  13951. 21,845, and pure blue is 43,690. The amount of black is set by the value for
  13952. brightness (meaning lightness in HLS, value in HSV), and the amount of color in
  13953. the mix is set by saturation. Pink in the HLS or HSV system would be obtained by
  13954. setting hue to red, saturation to some amount less than full, and brightness to
  13955. full.
  13956.  
  13957. The HLS and HSV systems are sufficiently similar that the Color Picker can treat
  13958. them as one by a simple expedient: the HLS model is treated by the Picker as if
  13959. it were ordered HSL; this puts hue and saturation in the same relative positions
  13960. in the data structures of both models.  
  13961.  
  13962. HSVColor = RECORD
  13963. hue:         SmallFract;  {fraction of circle, red at 0}
  13964. saturation:  SmallFract;  {0-1, 0 is gray, 1 is pure color}
  13965. value:       SmallFract   {0-1, 0 is black, 1 is max intensity}
  13966. END;
  13967.  
  13968. HSLColor = RECORD
  13969. hue:         SmallFract;  {fraction of circle, red at 0}
  13970. saturation:  SmallFract;  {0-1, 0 is gray, 1 is pure color}
  13971. lightness:   SmallFract   {0-1, 0 is black, 1 is white}
  13972. END;
  13973. _______________________________________________________________________________
  13974.  
  13975. æKY Color…Models…in…the…Dialog…Box
  13976. æC »Color Models in the Dialog Box                                    Color Picker Package
  13977. _______________________________________________________________________________
  13978.  
  13979. The controls in the dialog box are designed for use in the HSL or HSV models:
  13980. hue is chosen by moving the cursor around the color wheel, saturation by moving
  13981. in or out from the center, and brightness (value or lightness) is specified by
  13982. the scroll bar at the right. The way RGB values vary in response to the dialog
  13983. controls is not intuitive, but it can be instructive on how the models relate.
  13984.  
  13985. The dialog box cannot exactly match the print world’s additive effect, and it
  13986. does not offer CMYK controls, but routines for converting between RGB and CMY 
  13987. (cyan, magenta, yellow, without a black component) are included in the Color
  13988. Picker Package.
  13989.  
  13990. _______________________________________________________________________________
  13991.  
  13992. æKY Using…the…Color…Picker…Package…Vol…VI
  13993. æC »USING THE COLOR PICKER PACKAGE                                    Color Picker Package
  13994. _______________________________________________________________________________
  13995.  
  13996. Most developers will only use the Color Picker Package to display the Color
  13997. Picker’s dialog box.  A few developers may need to use the color model and
  13998. SmallFract conversion routines.
  13999.  
  14000. _______________________________________________________________________________
  14001.  
  14002. æKY Presenting…the…Dialog…Box
  14003. æC »Presenting the Dialog Box                                         Color Picker Package
  14004. _______________________________________________________________________________
  14005.  
  14006. Your program can present a user with the Color Picker dialog box, shown in
  14007. Figure 1, by calling the Color Picker’s GetColor function.
  14008.  
  14009. When called by an application, the Color Picker displays the dialog box,
  14010. including prompt text, which appears in the upper-left corner, and the initial
  14011. color, which appears in the lower of the two rectangles below the prompt. The
  14012. color being picked, in the upper rectangle, ranges over the entire color space
  14013. in response to the controls in the rest of the dialog box. Your application can
  14014. supply the prompt text, an initial color, the location of the upper-left corner
  14015. of the dialog box window, and whether it should appear on the main or deepest
  14016. screen.
  14017.  
  14018. The two groups of numeric fields (Hue/Saturation/Brightness and Red/Green/Blue)
  14019. show the parameters of the color being picked in the two color systems. The user
  14020. may increase or decrease the values using the arrow controls or enter values
  14021. directly into any of the six fields.
  14022.  
  14023. The range for all of the component values is 0 to 65,535. Larger values are
  14024. clipped to 65,535 after the user exits the field. When the user is increasing or
  14025. decreasing the hue using the arrow controls, 0 wraps around to 65,535, so the
  14026. user can circumnavigate the wheel with arrow controls just as with the cursor.
  14027. The hue value for pure red is 0; pure green is 21,845; pure blue is 43,690.
  14028.  
  14029. The user may select a single RGB value from Color QuickDraw’s entire range of
  14030. 248 color values. 
  14031.  
  14032. On black-and-white hardware (or in less than 4-bit mode), the display appears in
  14033. black and white; the Color Picker returns the RGB value selected, but does not
  14034. call any color routines in the course of responding to user actions.
  14035.   
  14036. On devices with a variable CLUT, the Color Picker temporarily borrows a color
  14037. table entry to display the exact color in the rectangle that shows the color
  14038. currently being picked. (As a result, when your application subsequently
  14039. displays the user’s chosen color, if you let the Color Manager approximate the
  14040. user’s value the result will probably differ somewhat from the one picked.)  The
  14041. Color Picker restores the color environment when it is done.
  14042.  
  14043. _______________________________________________________________________________
  14044.  
  14045. æKY Conversion…Facilities…Vol…VI
  14046. æC »Conversion Facilities                                             Color Picker Package
  14047. _______________________________________________________________________________
  14048.  
  14049. In addition to the GetColor function that puts up the Color Picker dialog box,
  14050. the Color Picker provides six procedures for converting between RGB and the CMY,
  14051. HLS, and HSV color systems; and two functions that convert between SmallFract
  14052. and fixed numbers. Most developers will use only the GetColor function.
  14053.  
  14054. The CMY, HSL, and HSV structures are defined by ColorPicker with SmallFract
  14055. values rather than INTEGER values (as used in RGBColor). A SmallFract value is
  14056. the fractional part of a Fixed number, which is the low-order word. The Integer
  14057. values in RGBColor are actually used as unsigned integer-sized values; by using
  14058. SmallFract values, the ColorPicker avoids sign extension problems in the
  14059. conversion math. The Color Picker provides two functions for converting between
  14060. SmallFract and fixed numbers. Most developers will not need to use these
  14061. facilities.
  14062.  
  14063. _______________________________________________________________________________
  14064.  
  14065. æKY Color…Picker…Routines
  14066. æC »COLOR PICKER ROUTINES                                             Color Picker Package
  14067. _______________________________________________________________________________
  14068.  
  14069. The following cards describe the Color Picker routines.
  14070. _______________________________________________________________________________
  14071.  
  14072. æKY Displaying…the…Color…Picker…Dialog…Box
  14073. æC »Displaying the Color Picker Dialog Box                            Color Picker Package
  14074. _______________________________________________________________________________
  14075.  
  14076. FUNCTION GetColor (where: Point; prompt: Str255; inColor: RGBColor; VAR        
  14077.  
  14078.                    outColor: RGBColor) : BOOLEAN;
  14079.  
  14080. The GetColor function displays the Color Picker dialog box on the screen, with
  14081. its upper-left corner located at the point you designate with the where
  14082. parameter. The Color Picker Package will display the dialog box and accept color
  14083. selection on any screen, not just the main screen. If where = (0,0), the dialog
  14084. box is positioned neatly on the main screen—centered horizontally and with
  14085. one-third of the empty space above the box and two-thirds below, whatever the
  14086. screen size. If an application supplies a where parameter of -1,-1, the Color
  14087. Picker will center the dialog box on what the Color Picker determines to be the
  14088. best screen, maximizing for depth and color.  
  14089.  
  14090. The prompt string is displayed in the upper-left corner of the dialog box. The
  14091. inColor parameter is the starting color, which the user may want for comparison;
  14092. it is displayed immediately below the current output color (the one the user is
  14093. picking). The OutColor parameter is set to the last color value the user picks,
  14094. if and only if the user clicks OK. On entry, it is treated as undefined, so the
  14095. output color sample originally matches the input. Although the color being
  14096. picked may vary widely, the input color sample remains fixed, and clicking in
  14097. the input sample resets the output color sample to match it.
  14098.  
  14099. GetColor returns TRUE if the user exits by clicking the OK button or FALSE if
  14100. the user cancels.
  14101.  
  14102. _______________________________________________________________________________
  14103.  
  14104. æKY Converting…Between…Color…Models
  14105. æC »Converting Between Color Models                                   Color Picker Package
  14106. _______________________________________________________________________________
  14107.  
  14108. These six routines offer conversions between RGB on the one hand and CMY, HSV,
  14109. or HSL on the other.
  14110.  
  14111. PROCEDURE  CMY2RGB (cColor: CMYColor; VAR rColor: RGBColor);
  14112.  
  14113. The CMY2RGB procedure converts a CMYColor record to an RGBColor record.
  14114.  
  14115. PROCEDURE  HSL2RGB (hColor: HSLColor; VAR rColor: RGBColor);
  14116.  
  14117. The HSL2RGB procedure converts an HSLColor record to an RGBcolor record.
  14118.  
  14119. PROCEDURE  HSV2RGB (hColor: HSVColor; VAR rColor: RGBColor);
  14120.  
  14121. The HSV2RGB procedure converts an HSVColor record to an RGBColor record.
  14122.  
  14123. PROCEDURE  RGB2CMY (rColor: RGBColor; VAR cColor: CMYColor);
  14124.  
  14125. The RGB2CMY procedure converts an RGBColor record to a CMYColor record.
  14126.  
  14127. PROCEDURE  RGB2HSL (rColor: RGBColor; VAR hColor: HSLColor);
  14128.  
  14129. The RGB2HSL procedure converts an RGBColor record to an HSLColor record.
  14130.  
  14131. PROCEDURE  RGB2HSV (rColor: RGBColor; VAR hColor: HSVColor);
  14132.  
  14133. The RGB2HSV procedure converts an RGBColor record to an HSVColor record.
  14134.  
  14135. _______________________________________________________________________________
  14136.  
  14137. æKY Converting…Between…SmallFract…and…Fixed…Values
  14138. æC »Converting Between SmallFract and Fixed Values                    Color Picker Package
  14139. _______________________________________________________________________________
  14140.  
  14141. A SmallFract value can represent a value between 0 and 65,535. They can be
  14142. assigned directly to and from Integers.
  14143.   
  14144. FUNCTION SmallFract2Fix(s: SmallFract): Fixed;
  14145.  
  14146. The SmallFract2Fix function converts a SmallFract value to a fixed integer. 
  14147.  
  14148. FUNCTION Fix2SmallFract(f: Fixed): SmallFract;
  14149.  
  14150. The Fix2SmallFract function converts a fixed integer to a SmallFract value. 
  14151. _______________________________________________________________________________
  14152.  
  14153. æKY Summary…of…the…Color…Picker…Package…Vol…VI
  14154. æC »SUMMARY OF THE COLOR PICKER PACKAGE                               Color Picker Package
  14155. _______________________________________________________________________________
  14156.  
  14157. The following cards summarize the constants, data types, and routines for the
  14158. Color Picker Package.
  14159. _______________________________________________________________________________
  14160.  
  14161. æKY Color…Picker…Package…Constants
  14162. æC »Constants                                                         Color Picker Package
  14163. _______________________________________________________________________________
  14164.  
  14165. CONST
  14166.  
  14167. MaxSmallFract  =  $0000FFFF;  {maximum SmallFract value, as LONGINT}
  14168. _______________________________________________________________________________
  14169.  
  14170. æKY  Color…Picker…Package…Data…Types
  14171. æC »Data Types                                                        Color Picker Package
  14172. _______________________________________________________________________________
  14173.  
  14174. TYPE
  14175. SmallFract = INTEGER;  {unsigned fraction between 0 and 1}
  14176.   HSVColor  = RECORD
  14177.     hue:         SmallFract;  {fraction of circle, red at 0}
  14178.     saturation:  SmallFract;  {0-1, 0 is gray, 1 is pure color}
  14179.     value:       SmallFract  {0-1, 0 is black, 1 is max intensity}
  14180.   END;
  14181.  
  14182.   HSLColor  = RECORD
  14183.   hue:          SmallFract;  {fraction of circle, red at 0}
  14184.   saturation:   SmallFract;  {0-1, 0 is gray, 1 is pure color}
  14185.   lightness:    SmallFract  {0-1, 0 is black, 1 is white}
  14186.   END;
  14187.  
  14188.   CMYColor  = RECORD   {CMY and RGB are complements}
  14189.   cyan:         SmallFract;
  14190.   magenta:      SmallFract;
  14191.   yellow:       SmallFract
  14192.   END;
  14193. _______________________________________________________________________________
  14194.  
  14195. æKY Color…Picker…Package…Routines…Vol…VI
  14196. æC »Routines                                                          Color Picker Package
  14197. _______________________________________________________________________________
  14198.  
  14199. Displaying the Dialog Box
  14200.  
  14201. FUNCTION GetColor  (where: Point; prompt: Str255; inColor: RGBColor; VAR
  14202. outColor: RGBColor) : BOOLEAN;
  14203.  
  14204. Converting Between Color Models
  14205.  
  14206. PROCEDURE  CMY2RGB  (cColor: CMYColor; VAR rColor: RGBColor);
  14207. PROCEDURE  HSL2RGB  (hColor: HSLColor; VAR rColor: RGBColor);
  14208. PROCEDURE  HSV2RGB  (hColor: HSVColor; VAR rColor: RGBColor);
  14209. PROCEDURE  RGB2CMY  (rColor: RGBColor; VAR cColor: CMYColor);
  14210. PROCEDURE  RGB2HSL  (rColor: RGBColor; VAR hColor: HSLColor);
  14211. PROCEDURE  RGB2HSV  (rColor: RGBColor; VAR hColor: HSVColor);
  14212.  
  14213. Converting Between SmallFract and Fixed Values
  14214.  
  14215. FUNCTION SmallFract2Fix  (s: SmallFract): Fixed;
  14216. FUNCTION Fix2SmallFract  (f: Fixed): SmallFract;
  14217. _______________________________________________________________________________
  14218.  
  14219. æKY  Assembly…Language…Information…for…Color…Picker…Package
  14220. æC »Assembly Language Information                                     Color Picker Package
  14221. _______________________________________________________________________________
  14222.  
  14223. Constants
  14224.  
  14225. Fix2SmallFract  .EQU  1  ; selector for Fix2SmallFract
  14226. SmallFract2Fix  .EQU  2  ; selector for mallFract2Fix
  14227. CMY2RGB         .EQU  3  ; selector for CMY2RGB
  14228. RGB2CMY         .EQU  4  ; selector for RGB2CMY
  14229. HSL2RGB         .EQU  5  ; selector for HSL2RGB
  14230. RGB2HSL         .EQU  6  ; selector for RGB2HSL
  14231. HSV2RGB         .EQU  7  ; selector for HSV2RGB
  14232. RGB2HSV         .EQU  8  ; selector for RGB2HSV
  14233. GetColor        .EQU  9  ; selector for GetColor
  14234.  
  14235. Macro
  14236.   _Pack12
  14237. _______________________________________________________________________________
  14238.  
  14239.  
  14240.  
  14241. æKY About…The…ColorPickerPackage…Chapter
  14242. æC »ABOUT THIS CHAPTER                                     ColorPickerPackage
  14243. _______________________________________________________________________________
  14244.  
  14245. Warning:  This chapter has not been updated to reflect changes and improvements
  14246.           that are available on systems using 32-Bit QuickDraw.  For further
  14247.           information on 32-Bit QuickDraw, please refer to the 32-Bit QuickDraw
  14248.           documentation (available on “Phil & Dave’s Excellent CD: The Release
  14249.           Version).
  14250.  
  14251. This chapter describes the Color Picker, a package that allows applications to present
  14252. users with a standard interface for color selection.  You should be familiar with
  14253. color on the Macintosh and graphic devices, as discussed in the Color QuickDraw and
  14254. Graphic Devices chapters.
  14255. _______________________________________________________________________________
  14256.  
  14257.  
  14258. æKY The…Color…Picker…Package
  14259. æC »THE COLOR PICKER PACKAGE                               ColorPickerPackage
  14260. _______________________________________________________________________________
  14261.  
  14262. The Color Picker Package is a tool that applications can use to present a standard
  14263. user interface for color selection.  It also provides routines for converting color
  14264. values between several different color systems.  The Color Picker Package does not
  14265. alter the Color Look-Up Table (CLUT), if any, associated with the current graphics
  14266. device.
  14267.  
  14268. Once the user chooses a color, Color Picker returns it to the application, in the
  14269. form of an RGBColor value, leaving the graphics device in its original state.  The
  14270. application can do what it likes with the color selection, with as much or as little
  14271. attention to the available graphics hardware as it deems appropriate.  On black and
  14272. white hardware (or in less than 4-bit mode), the display is in black and white; Color
  14273. Picker returns the value selected, but does not call any color routines.
  14274.  
  14275. On direct device hardware the exact color can be used without extra effort, while on
  14276. fixed CLUT hardware it can only be approximated.  On most hardware, such as Apple’s
  14277. TFB graphics card, which has a variable CLUT, the application decides how faithfully
  14278. to reproduce the color, because it can replace an entry in the device’s CLUT to show
  14279. it exactly, or treat the table as fixed and approximate the color.  Color Picker
  14280. itself takes advantage of the hardware on such devices, displaying the exact color by
  14281. borrowing a color table entry.  As result, applications that are content to approximate
  14282. the color will show users colors that differ somewhat from the ones picked.
  14283.  
  14284. _______________________________________________________________________________
  14285.  
  14286.  
  14287. æKY The…Color…Picker…Dialog…Box
  14288. æC »THE COLOR PICKER DIALOG BOX                            ColorPickerPackage
  14289. _______________________________________________________________________________
  14290.  
  14291. Developers can present the Color Picker dialog box, shown in Figures 1 & 2
  14292. (This illustration is in color in Figure 1 if you are using a color monitor in color
  14293. mode.), to a user by means of the Color Picker routine, described later in this
  14294. chapter.
  14295.  
  14296. •••Refer to Figure 1.•••
  14297.  
  14298. Figure 1–Color Picker Dialog Box (Color Version)
  14299.  
  14300. •••Refer to Figure 2.•••
  14301.  
  14302. Figure 2–Color Picker Dialog Box (B/W Version)
  14303.  
  14304. When called by an application, the Color Picker supplies the prompt text, which
  14305. appears in the upper-left corner, and the initial color, which appears in the bottom
  14306. of the two rectangles below the prompt.  The color being picked, in the upper rectangle,
  14307. ranges rapidly over the entire color space, in response to the controls in the rest
  14308. of the dialog.  The calling application also supplies the location of the top-left
  14309. corner of the dialog window.
  14310.  
  14311. The user is allowed to select a single color, from the entire range the hardware can
  14312. produce.  The wheel allows users to select a given hue and saturation simultaneously.
  14313.  The center of the wheel displays zero saturation
  14314. (no hue mixed in); the outer boundary is maximum saturation (no gray mixed in);
  14315. colors on the edge of the wheel are pure hues.  The scroll bar at right controls the
  14316. brightness (value) of the wheel.
  14317.  
  14318. The two groups of text fields (Hue/Saturation/Brightness and Red/Green/Blue) show the
  14319. parameters of the color being picked in two independent color systems.  Brightness
  14320. represents value in the HSV model.
  14321.  
  14322. The HSV values are the primary color system, which correspond to the controls in the
  14323. dialog box.  The RGB values are the alternate color system, and the way they vary in
  14324. response to the dialog controls is not intuitive.  Only users who understand both
  14325. color systems will understand how the RGB values vary in relation to the rest of the
  14326. dialog.  (See the Color Quickdraw chapter for more information.)  The alternate color
  14327. system is intended to make life easier for users accustomed to something other than
  14328. the HSV model.
  14329.  
  14330. The range for all of the component values is 0 to 65,535.  Larger values are clipped
  14331. to the maximum after the user exits the field.  When incrementing or decrementing the
  14332. hue via the arrow controls, 0 wraps around to 65,535, and vice versa, so the user can
  14333. circumnavigate the wheel unimpeded.  The hue value for red is 0; green is 21,845;
  14334. blue is 43,690.
  14335.  
  14336. _______________________________________________________________________________
  14337.  
  14338.  
  14339. æKY Color…Picker…Package…Routines
  14340. æC »COLOR PICKER PACKAGE ROUTINES                          ColorPickerPackage
  14341. _______________________________________________________________________________
  14342.  
  14343. FUNCTION GetColor(where: Point; prompt: Str255; inColor: RGBColor;
  14344.                   VAR outColor: RGBColor) : BOOLEAN;
  14345.  
  14346. GetColor displays the Color Picker dialog box on the screen, with its top-left corner
  14347. located at where. (The where Point should be on the main gDevice.)  If where = (0,0),
  14348. the dialog box is positioned neatly on the screen, centered horizontally, and with
  14349. one third of the empty space above the box, two thirds below, whatever the screen
  14350. size.
  14351.  
  14352. The prompt string is displayed in the upper-left corner of the dialog box.  InColor
  14353. is the starting color, which the user may want for comparison, and is displayed
  14354. immediately below the current output color (the one the user is picking).  OutColor
  14355. is set to the last color value the user picked, if and only if the user clicks OK.  
  14356. On entry, it is treated as undefined, so the output color sample originally matches
  14357. the input.  While the color being picked may vary widely, the input color sample
  14358. remains fixed, and clicking in the input sample resets the output color sample to
  14359. match it.
  14360.  
  14361. GetColor returns TRUE if the user exits via the OK button, or FALSE if the user
  14362. cancels.
  14363.  
  14364. Assembly-language note:  the trap macro for the Color Picker Package is
  14365.                          _Pack12. The routine selectors are as follows:
  14366.  
  14367.                            Fix2SmallFract  .EQU    1
  14368.                            SmallFract2Fix  .EQU    2
  14369.                            CMY2RGB         .EQU    3
  14370.                            RGB2CMY         .EQU    4
  14371.                            HSL2RGB         .EQU    5
  14372.                            RGB2HSL         .EQU    6
  14373.                            HSV2RGB         .EQU    7
  14374.                            RGB2HSV         .EQU    8
  14375.                            GetColor        .EQU    9
  14376.  
  14377. _______________________________________________________________________________
  14378.  
  14379.  
  14380. æKY Conversion…Facilities
  14381. æC »CONVERSION FACILITIES                                  ColorPickerPackage
  14382. _______________________________________________________________________________
  14383.  
  14384. The Color Picker provides six procedures for converting color values between CMY and
  14385. RGB, and between HSL or HSV and RGB.  Most developers will not need to use these
  14386. routines.
  14387.  
  14388. PROCEDURE  CMY2RGB (cColor: CMYColor; VAR rColor: RGBColor);
  14389. PROCEDURE  RGB2CMY (rColor: RGBColor; VAR cColor: CMYColor);
  14390. PROCEDURE  HSL2RGB (hColor: HSLColor; VAR rColor: RGBColor);
  14391. PROCEDURE  RGB2HSL (rColor: RGBColor; VAR hColor: HSLColor);
  14392. PROCEDURE  HSV2RGB (hColor: HSVColor; VAR rColor: RGBColor);
  14393. PROCEDURE  RGB2HSV (rColor: RGBColor; VAR hColor: HSVColor);
  14394.  
  14395. For developmental simplicity in switching between the HLS and HSV models, HLS is
  14396. reordered into HSL. Thus both models start with hue and saturation values; value/lightness/brightness
  14397. is last.
  14398.  
  14399. The CMY, HSL, and HSV structures are defined by ColorPicker with SmallFract values
  14400. rather than INTEGER values (as in RGBColor).  A SmallFract value is the fractional
  14401. part of a Fixed number, which is the low-order word.  The INTEGER values in RGBColor
  14402. are actually used as unsigned integer-sized values; by using SmallFracts, ColorPicker
  14403. avoids sign extension problems in the conversion math.
  14404.  
  14405. The Color Picker provides two functions for converting between SmallFract and Fixed
  14406. numbers.  Most developers will not need to use these facilities.
  14407.  
  14408. FUNCTION Fix2SmallFract(f: Fixed): SmallFract;
  14409. FUNCTION SmallFract2Fix(s: SmallFract): Fixed;
  14410.  
  14411. A SmallFract can represent a value between 0 and  65,535.  They can be assigned
  14412. directly to and from INTEGERs.
  14413.  
  14414. _______________________________________________________________________________
  14415.  
  14416.  
  14417. æKY Summary…of…the…Color…Picker…Package
  14418. æC »SUMMARY OF THE COLOR PICKER PACKAGE                    ColorPickerPackage
  14419. _______________________________________________________________________________
  14420.  
  14421. Constants
  14422.  
  14423. CONST
  14424.   MaxSmallFract  =  $0000FFFF;    {maximum SmallFract value, as LONGINT}
  14425.  
  14426. _______________________________________________________________________________
  14427.  
  14428. Data Types
  14429.  
  14430. TYPE
  14431.   SmallFract  = INTEGER;     {unsigned fraction between 0 and 1}
  14432.  
  14433.   HSVColor = RECORD
  14434.                hue:         SmallFract;  {fraction of circle, red at 0}
  14435.                saturation:  SmallFract;  {0-1, 0 is gray, 1 is pure color}
  14436.                value:       SmallFract;  {0-1, 0 is black, 1 is max intensity}
  14437.              END;
  14438.  
  14439.   HSLColor = RECORD
  14440.                hue:         SmallFract;  {fraction of circle, red at 0}
  14441.                saturation:  SmallFract;  {0-1, 0 is gray, 1 is pure color}
  14442.                lightness:   SmallFract;  {0-1, 0 is black, 1 is white}
  14443.              END;
  14444.  
  14445.   CMYColor = RECORD    {CMY and RGB are complements}
  14446.                cyan:     SmallFract;
  14447.                magenta:  SmallFract;
  14448.                yellow:   SmallFract;
  14449.              END;
  14450.  
  14451. _______________________________________________________________________________
  14452.  
  14453. Routines
  14454.  
  14455. FUNCTION  GetColor(where: Point; prompt: Str255; inColor: RGBColor;
  14456.                    VAR outColor: RGBColor): BOOLEAN;
  14457.  
  14458. Conversion Functions
  14459.  
  14460. FUNCTION  Fix2SmallFract(f: Fixed): SmallFract;
  14461. FUNCTION  SmallFract2Fix(s: SmallFract): Fixed;
  14462.  
  14463. Color Conversion Procedures
  14464.  
  14465. PROCEDURE CMY2RGB(cColor: CMYColor; VAR rColor: RGBColor);
  14466. PROCEDURE RGB2CMY(rColor: RGBColor; VAR cColor: CMYColor);
  14467. PROCEDURE HSL2RGB(hColor: HSLColor; VAR rColor: RGBColor);
  14468. PROCEDURE RGB2HSL(rColor: RGBColor; VAR hColor: HSLColor);
  14469. PROCEDURE HSV2RGB(hColor: HSVColor; VAR rColor: RGBColor);
  14470. PROCEDURE RGB2HSV(rColor: RGBColor; VAR hColor: HSVColor);
  14471.  
  14472. _______________________________________________________________________________
  14473.  
  14474. Assembly-Language Information
  14475.  
  14476. Constants
  14477.  
  14478. Fix2SmallFract  .EQU    1
  14479. SmallFract2Fix  .EQU    2
  14480. CMY2RGB         .EQU    3
  14481. RGB2CMY         .EQU    4
  14482. HSL2RGB         .EQU    5
  14483. RGB2HSL         .EQU    6
  14484. HSV2RGB         .EQU    7
  14485. RGB2HSV         .EQU    8
  14486. GetColor        .EQU    9
  14487.  
  14488. Macro
  14489.  
  14490. _PACK12
  14491.  
  14492. Further Reference:
  14493. _______________________________________________________________________________
  14494. Color QuickDraw
  14495. Graphics Devices
  14496. 32-Bit QuickDraw Documentation
  14497.  
  14498. æKY Color QuickDraw
  14499. æC 
  14500. _______________________________________________________________________________
  14501.  
  14502. COLOR QUICKDRAW
  14503. _______________________________________________________________________________
  14504.  
  14505. About…The…Color…Quickdraw…Vol…VI…Chapter
  14506. About…Color…Quickdraw…Vol…VI
  14507. Direct…Colors
  14508.     PixMap…Record…Extensions
  14509.     Direct…Pixel…Examples
  14510.     PICT…Extensions
  14511. Well-Behaved…Graphics…Applications
  14512. Using…Color…Quickdraw…Vol…VI
  14513.     Copying…PixMap…Records
  14514.     Dithering
  14515.     Resizing…Images
  14516.     Luminance…Mapping
  14517.     Image…Resolution
  14518.     Importing…PixMap…Records
  14519.     Exporting…PixMap…Records
  14520.     Converting…a…Bitmap…to…a…Region
  14521.     Checking…that…QuickDraw…is…Done
  14522. New…Color…Quickdraw…Routines
  14523.     New…QuickDraw…Result…Codes
  14524.     Creating…an…Extended…PICT2…Picture
  14525.     From…Bitmap…to…Region
  14526.     Drawing…Completion
  14527.     Reporting…Data…Structure…Changes
  14528. The…Extended…PICT2…Format
  14529.     Sample…Extended…PICT2…File
  14530.     PICT2…Opcode…Types
  14531.     Extended…PICT2…Opcodes
  14532. Summary…of…Color…Quickdraw…Vol…VI…Changes
  14533.     Color…Quickdraw…Constants
  14534.     Color…Quickdraw…Data…Types
  14535.     Color…Quickdraw…Vol…VI…Routines
  14536.     Color…Quickdraw…Result…Codes
  14537.  
  14538. About…The…ColorQuickDraw…Chapter
  14539. Color…Representation
  14540. Using…Color…on…the…Macintosh…II
  14541. About…Color…QuickDraw
  14542. The…Color…Graphics…Port
  14543. The…Color…Cursor
  14544. Color…Icons
  14545. Using…Color…QuickDraw
  14546. Color…QuickDraw…Routines
  14547. Color…QuickDraw…Resource…Formats
  14548. Using…Text…with…QuickDraw
  14549. Color…Picture…Format
  14550. PICT…Opcodes
  14551. Summary…of…Color…QuickDraw
  14552. _______________________________________________________________________________
  14553.  
  14554.  
  14555.  
  14556. æKY About…The…Color…Quickdraw…Vol…VI…Chapter
  14557. æC »ABOUT THIS CHAPTER                                                     Color QuickDraw
  14558. _______________________________________________________________________________
  14559.  
  14560. This chapter describes extensions to Color QuickDraw. You should be familiar
  14561. with the Graphics Overview in this volume, and with the Color QuickDraw
  14562. description in Inside Macintosh, Volume V. Developers of graphics cards and
  14563. drivers should also be familiar with the Slot Manager, Graphics Devices Manager,
  14564. and the Control Panel as described in both Inside Macintosh and and Developing
  14565. Cards and Drivers for the Macintosh Family, second edition.
  14566.  
  14567. This chapter describes extensions to the color facilities of Color QuickDraw,
  14568. and other new features, notably luminance mapping techniques and routines by
  14569. which existing applications can signal QuickDraw that a data structure has been
  14570. modified directly, rather than by use of QuickDraw routines.
  14571.  
  14572. If you use offscreen graphics to prepare images before copying them to the
  14573. screen, read the Graphics Devices Manager chapter in this volume for a
  14574. description of new routines that considerably reduce the complexity of that
  14575. task. 
  14576. _______________________________________________________________________________
  14577.  
  14578. æKY About…Color…Quickdraw…Vol…VI
  14579. æC »ABOUT COLOR QUICKDRAW                                                  Color QuickDraw
  14580. _______________________________________________________________________________
  14581.  
  14582. Color QuickDraw now supports images that use direct, as well as indexed,
  14583. specification of colors.
  14584.  
  14585. Although an application specifies a color in terms of RGB space, the actual
  14586. value Color QuickDraw sends to the graphics card frame buffer (video RAM) is an
  14587. index value, which is used as input to the CLUT. An 8-bit index can specify 256
  14588. different entries (2 to the 8th power). On CLUT devices, the relationship
  14589. between the index value and the color generated depends on what colors are
  14590. currently stored where in the table.
  14591.  
  14592. At the cost of larger RAM requirements and, in some situations, slower
  14593. performance, direct color specification eliminates the need for table look-ups
  14594. and color searching algorithms, and lets your application directly specify over
  14595. 16 million colors. (For a comparison of the differences between indexed and
  14596. direct colors, see the Graphics Overview chapter.)
  14597.  
  14598. In addition to direct color, Color QuickDraw now also provides
  14599.  
  14600.   •   support for a true gray-scale display, providing better image fidelity on
  14601.       gray-scale devices
  14602.  
  14603.   •   a routine that converts a BitMap record into a region, which means you
  14604.       can, in effect, use region-manipulating routines on BitMap records
  14605.  
  14606.   •   four routines that enable you to signal Color QuickDraw when your
  14607.       application directly modifies a CLUT, PixPat, GrafPort, or GDevice data
  14608.       structure. (Direct modification is still discouraged.)
  14609.  
  14610.   •   a routine that creates and retrieves pictures with variable dots per inch
  14611.       resolution
  14612. _______________________________________________________________________________
  14613.  
  14614. æKY Direct…Colors
  14615. æC »DIRECT COLORS                                                          Color QuickDraw
  14616. _______________________________________________________________________________
  14617.  
  14618. Color QuickDraw now supports pixmaps with direct color specification as well as
  14619. the indexed method supported by the original release of Color QuickDraw. Since
  14620. QuickDraw has always striven to be device-independent, many applications need
  14621. make no changes. If your application specifies RGB colors, the system determines
  14622. the best colors for indexed devices and passes your RGB color to direct devices.
  14623.  
  14624. Changes to the Color QuickDraw interface affect only these two
  14625. color-specification data structures:
  14626.  
  14627.   •   the PixMap data structure that describes an image
  14628.  
  14629.   •   the PICT2 format in which images and graphics drawing operations are
  14630.       stored
  14631.  
  14632. Extensions to these two structures are described next.  
  14633. _______________________________________________________________________________
  14634.  
  14635. æKY PixMap…Record…Extensions
  14636. æC »PixMap Record Extensions                                               Color QuickDraw
  14637. _______________________________________________________________________________
  14638.  
  14639. Color QuickDraw supports two new pixel formats, corresponding to 16-bit and
  14640. 32-bit pixel depths. In both cases, the pixel’s displayed color is specified by
  14641. the pixel value; the pixel value is not an index into a CLUT. 
  14642.  
  14643. Note that the format of a PixMap record is not changed from that introduced with
  14644. the Macintosh II, but six PixMap fields can have new values. The PixMap data
  14645. structure is shown here, only the fields that can have new values are discussed.
  14646. See the Color QuickDraw chapter in Volume V for a complete PixMap description.
  14647.  
  14648. PixMap = RECORD
  14649. baseAddr:   Ptr;      {pointer to PixMap data}
  14650. rowBytes:   Integer;  {offset to next row} 
  14651. bounds:     Rect;     {boundary rectangle} 
  14652. pmVersion:  Integer;  {Color QuickDraw flags} 
  14653. packType:   Integer;  {packing format}
  14654. packSize:   Longint;  {size of data in packed state}
  14655. hRes:       Fixed;    {horizontal resolution}
  14656. vRes:       Fixed;    {vertical resolution}
  14657. pixelType:  Integer;  {format of pixel image}
  14658. pixelSize:  Integer;  {physical bits per pixel}
  14659. cmpCount:   Integer;  {logical components per pixel}
  14660. cmpSize:    Integer;  {logical bits per component}
  14661. planeBytes: Longint;  {offset to next plane}
  14662. pmTable:    CTabHandle; {absolute colors for this image}
  14663. pmReserved: Longint   {reserved for future expansion}
  14664. END;
  14665.  
  14666. Direct fields
  14667.  
  14668. rowBytes:  The restriction that rowbytes be less than $2000 has been relaxed:
  14669. rowbytes must be less than $4000. RowBytes must be even, and for best
  14670. performance it should be a multiple of 4.
  14671.   
  14672. pmVersion:  Normally 0. If pmVersion is 4, Color QuickDraw treats the pixmap’s
  14673. baseAddr as being 32-bit clean. This flag can be set by a new Graphics Devices
  14674. Manager routine, SetPMVersion. Most applications never need to set this field;
  14675. it is for low-level driver support.
  14676.  
  14677. pixelType:  Direct pixel values are specified by a pixelType field value of
  14678. RGBDirect, or 16. In a PixMap record of the gDevice record for a direct device,
  14679. the pixelType field will be set to the constant RGBDirect when the screen depth
  14680. is set.
  14681.  
  14682. pixelSize:  Pixel sizes must be a power of two. Color QuickDraw supports pixel
  14683. sizes of 1, 2, 4, and 8 bits; Color QuickDraw adds pixel sizes of 16 and 32
  14684. bits. 
  14685. cmpCount  
  14686.  
  14687. cmpCount:  With indexed pixels, each pixel is a single value representing an
  14688. index into a color table, and therefore the cmpCount field of a PixMap record is
  14689. 1—the index is the single component. With direct pixels, each pixel contains
  14690. three components, one integer each for the intensities of red, green, and blue,
  14691. and cmpCount is 3. Other values are undefined.
  14692.  
  14693. cmpSize:  The cmpSize field specifies the size of each component. A 32-bit pixel
  14694. consists of three components (red, green, and blue values) of 8 bits each. Since
  14695. cmpCount * cmpSize (3 * 8 = 24) is less than the value of pixelSize, 8 bits in
  14696. the pixel are not part of any component. These bits are unused: Color QuickDraw
  14697. sets them to zero in any image it creates, and if presented with a 32-bit image,
  14698. for example in CopyBits, it passes whatever bits are there. (Generally,
  14699. therefore, your application should clear image memory to 0 before creating a
  14700. 32-bit image.)
  14701.  
  14702. A 16-bit pixel consists of three components of 5 bits each. This leaves an
  14703. unused high-order bit, which QuickDraw sets to 0.
  14704.  
  14705. Color QuickDraw expects that the sizes of all components are the same, and that
  14706. cmpCount * cmpSize is less than or equal to pixelSize.
  14707.  
  14708. In each direct pixel, the pixel value is the concatenation of the red, green,
  14709. and blue components, where red is in the most significant bits and blue is in
  14710. the least significant. The entire direct pixel is right justified; unused bits
  14711. occupy the highest-order bits. 
  14712. _______________________________________________________________________________
  14713.  
  14714. æKY Direct…Pixel…Examples
  14715. æC »Direct Pixel Examples                                                  Color QuickDraw
  14716. _______________________________________________________________________________
  14717.  
  14718. Figure 16-1 shows a 32-bit direct pixel value, in which the pixel and component
  14719. fields have been set up as
  14720.  
  14721. pixelType  =  16;  {RGBDirect}
  14722. pixelSize  =  32;  {must be a power of 2}
  14723. cmpCount  =  3;    {red, green, and blue values}
  14724. cmpSize  =  8;     {8 bits for each component}
  14725.  
  14726. ø 16.1  A 32-bit direct pixel
  14727.  
  14728. In this example, the pixel value (hexadecimal) is $00178609, which deconstructs
  14729. into component values of $17 red, $86 green, and $09 blue, resulting in a medium
  14730. green. Figure 16-2 approximates the same color as in Figure 16-1 using a 16-bit
  14731. pixel specified as follows:
  14732.   
  14733. pixelType  =  16;  {RGBDirect}
  14734. pixelSize  =  16;  {Must be a power of 2}
  14735. cmpCount  =  3;    {red, green, and blue values}
  14736. cmpSize  =  5;     {5 bits for each component}
  14737.       
  14738. ø 16.2  A 16-bit direct pixel
  14739.  
  14740. Here the pixel value is $0A01, with component values of $02, $10, and $01 for
  14741. red, green and blue.
  14742.  
  14743. When converting a 32-bit pixel value to 16 bits, the three least significant
  14744. bits are dropped for each component. When converting a 16-bit pixel value to 32
  14745. bits, the most significant three bits of each component are replicated and added
  14746. to constitute the least significant three bits of the resulting 8-bit component,
  14747. as illustrated in Figure 16-3.
  14748.  
  14749. ø 16.3  Converting a 16-bit direct pixel to 32-bit direct
  14750.  
  14751. In this way, white stays white, black stays black, and other values are spread
  14752. appropriately.
  14753.  
  14754. Figures 16-4 to  16-9 show first how Color QuickDraw converts a full 48-bit RGB
  14755. color to 32, 16, and 8 bit values (the latter indexed), and then the reverse
  14756. process, of converting those values back to 48 bits.
  14757.  
  14758. ø 16.4  Converting a 48-bit RGB value to 32-bit direct
  14759.  
  14760. A 32-bit direct pixel uses the most significant 8 bits of each component, and
  14761. has an 8-bit pad.
  14762.  
  14763. ø 16.5  Converting a 48-bit RGB value to 16-bit direct
  14764.  
  14765. A 16-bit direct pixel uses the most significant 5 bits of each component, and
  14766. has a 1-bit pad.
  14767.  
  14768. ø 16.6  Converting a 48-bit value to an 8 bit index
  14769.  
  14770. To obtain an 8-bit pixel value, the Color Manager determines the closest RGB
  14771. value in the CLUT; its index value is stored in the 8-bit pixel. In the standard
  14772. 8-bit CLUT, from 'CLUT' resource with ID of 8, the nearest value to the original
  14773. RGB value of Figure 16-4 is in table entry 161. Note that with indexed pixels,
  14774. the pixel value has no direct relation to the original RGB value.
  14775.  
  14776. ø 16.7  Converting an 32-bit  pixel to 48 bits
  14777.  
  14778. Color QuickDraw expands a 32-bit pixel into a 48-bit value by dropping the pad
  14779. byte and doubling each 8-bit component.  Note that the resulting 48-bit value
  14780. differs (in the least significant 8 bits of each component) from the original in
  14781. Figure 16-4.
  14782.  
  14783. ø 16.8  Converting an 16-bit  pixel to 48 bits
  14784.  
  14785. Color QuickDraw expands a 16-bit pixel into a 48-bit value by dropping the pad
  14786. bit and inserting three copies of each 5-bit component and a copy of the most
  14787. significant bit into each 16-bit component of the destination. Note that the
  14788. result differs (in the least significant 11 bits of each component) from the
  14789. original value.
  14790.  
  14791. ø 16.9  Converting an 8-bit  indexed pixel to 48 bits
  14792.  
  14793. Color QuickDraw expands an 8-bit indexed pixel into a 48-bit value by taking the
  14794. 48-bit value pointed to in the CLUT. The difference between this value and the
  14795. original 48-bit value varies, depending on the CLUT values.
  14796.  
  14797. _______________________________________________________________________________
  14798.  
  14799. æKY PICT…Extensions
  14800. æC »PICT Extensions                                                        Color QuickDraw
  14801. _______________________________________________________________________________
  14802.  
  14803. The PICT2 picture format defined for Color QuickDraw only supports images
  14804. consisting of CLUT indices. The PICT2 format has been expanded so that it can
  14805. record images with pixels that directly specify a given color.
  14806.  
  14807. To the current imaging opcodes BitsRect, BitsRgn, PackBitsRect, and PackBitsRgn,
  14808. Color QuickDraw adds DirectBitsRect and DirectBitsRgn. These opcodes enable your
  14809. application to cut, paste, and store images with up to 32 bits of color
  14810. information per pixel.
  14811.  
  14812. A new routine, the OpenCPicture function, lets your application create a PICT2
  14813. file and pass rectangle and resolution information, which is stored in the PICT2
  14814. header. This provides a simple mechanism for creating images with spatial
  14815. resolution other than 72 dpi. The OpenCPicture function is described in “New
  14816. Color QuickDraw Routines” later in this chapter.
  14817.  
  14818. The following opcodes occur only in pictures using the extended PICT2 format.
  14819. Two new opcodes specify direct pixels: 
  14820.  
  14821. DirectBitsRect  EQU  $9A    ; direct data copybits, rect clipped
  14822. DirectBitsRgn   EQU  $9B    ; direct data copybits, rgn clipped 
  14823.  
  14824. In addition, an opcode has been defined to specify font information:
  14825.  
  14826. FontName        EQU    $2C    ; font ID and name
  14827.  
  14828. The PICT2 format is described fully in “The Extended PICT2 Format.”
  14829. _______________________________________________________________________________
  14830.  
  14831. æKY Well-Behaved…Graphics…Applications
  14832. æC »WELL-BEHAVED GRAPHICS APPLICATIONS                                     Color QuickDraw
  14833. _______________________________________________________________________________
  14834.  
  14835. Over the years, some developers have written applications that modify the
  14836. QuickDraw data structures directly rather than using the routines provided for
  14837. that purpose. Then, when Apple engineers improve QuickDraw, the applications
  14838. break.  
  14839.  
  14840. As both QuickDraw and graphics applications grow more complex, the problem
  14841. becomes acute. This section points to new routines you can use to signal
  14842. QuickDraw when your application modifies certain data structures directly so
  14843. that QuickDraw can take note and act accordingly. 
  14844.  
  14845. Applications should not directly change fields in QuickDraw data structures, but
  14846. use the following procedures instead:
  14847.  
  14848.  
  14849. AddComp        AddSearch           BackColor
  14850. BackPat        BackPixPat          CharExtra
  14851. ClipRect       ColorBit            CopyPixPat
  14852. DelComp        DelSearch           ForeColor
  14853. GrafDevice     HideCursor          HidePen
  14854. HiliteColor    MakeRGBPat          Move
  14855. MovePortTo     MoveTo              ObscureCursor
  14856. OpColor        PenMode             PenNormal
  14857. PenPat         PenPixPat           PenSize
  14858. PortSize       RGBBackColor        RGBForeColor
  14859. SetCCursor     SetClientID         SetClip
  14860. SetCursor      SetDeviceAttribute  SetGDevice
  14861. SetOrigin      SetPenState         SetPort
  14862. SetPortBits    SetPortPix          ShowCursor
  14863. ShowPen        SpaceExtra          TextFace
  14864. TextFont       TextMode            TextSize
  14865.  
  14866. Using these routines rather than directly modifying the data structures ensures
  14867. that your application will fully benefit from any future improvements to
  14868. QuickDraw. In particular, the OffscreenGWorld routines described in the Graphics
  14869. Devices Manager chapter of this volume remove much of the need for directly
  14870. modifying graphics data structures.
  14871.  
  14872. Apple strongly recommends that new applications follow these guidelines.  
  14873. However, it is possible to make existing applications better-behaved by calling
  14874. one of the following procedures after directly changing a QuickDraw data
  14875. structure and before making any other QuickDraw call:
  14876.  
  14877.   CTabChanged 
  14878.   PixPatChanged 
  14879.   PortChanged
  14880.   GDeviceChanged
  14881.  
  14882. These routines inform QuickDraw that a direct modification has occurred so it
  14883. can update its world. They are described in the “New Color QuickDraw
  14884. Routines”section.
  14885.  
  14886. _______________________________________________________________________________
  14887.  
  14888. æKY Using…Color…Quickdraw…Vol…VI
  14889. æC »USING COLOR QUICKDRAW                                                  Color QuickDraw
  14890. _______________________________________________________________________________
  14891.  
  14892. If your application uses color in straightforward ways it will probably execute
  14893. without change in a direct pixel environment. 
  14894.  
  14895. For most other applications, the main concern is in the creation and use of
  14896. special-purpose PixMap and GDevice records—and by using the OffscreenGWorld
  14897. routines described in the Graphics Devices Manager chapter you will find such
  14898. tasks far easier than before. 
  14899.  
  14900. If you must work with GrafPort, PixMap, and GDevice records in ways beyond the
  14901. scope of the OffscreenGWorld routines, the following guidelines may aid you in
  14902. adapting to Color QuickDraw’s direct pixel environment:
  14903.  
  14904.   •   Don’t draw directly to the screen. A screen baseAddr is only guaranteed
  14905.       to be a valid pointer in 32-bit addressing mode.
  14906.  
  14907.   •   Don’t directly change the fgColor or bkColor fields of a grafPort and
  14908.       expect them to be used as the pixel values. Color QuickDraw recalculates
  14909.       these values for each device. If you really want to draw in an index
  14910.       instead of a color, use a palette with pmExplicit colors, as described in
  14911.       the Palette Manager chapter in this volume. For device independant colors
  14912.       use the RGBForeColor and RGBBackColor procedures.
  14913.  
  14914.   •   Fill out all the fields in a new PixMap record. The NewPixMap function
  14915.       returns a PixMap record that has been cloned from TheGDevice record’s
  14916.       PixMap record. If you don’t want a copy of the main screen’s PixMap
  14917.       record—for example, you want one that is a different depth—then you must
  14918.       fill out more fields than just pixelSize: you must fill out the
  14919.       pixelType, cmpCount, and cmpSize fields. Set pmVersion to 0 when
  14920.       initializing your own PixMap record. For future compatibility you should
  14921.       also set packType, packSize, planeBytes, and pmReserved to 0.
  14922.  
  14923.   •   Don’t clone a graphic device record’s PixMap record. Instead, use the
  14924.       NewPixmap function or the CopyPixMap procedure. If you must create or
  14925.       manually clone a PixMap record, make sure to set the pmVersion field and
  14926.       other unused fields to 0 for future compatibility.
  14927.  
  14928.   •   Fill out all the fields of a new GDevice. When creating an offscreen
  14929.       graphic device record by calling NewGDevice with a mode of -1, you must
  14930.       fill out the fields of the graphic device record (for instance, gdType)
  14931.       yourself. If you want a copy of an existing graphic device record, then
  14932.       copy the gdType field from it. If you explicitly want an indexed device
  14933.       then, set gdType to 0.
  14934.   •   Don’t assume a PixMap record has a CLUT. Direct PixMap records need not
  14935.       have CLUTs. For compatibility, direct PixMap records should have dummy
  14936.       pmTable handles that point to color table headers with seed values equal
  14937.       to cmpSize * cmpCnt, and the ctSize field should be set to 0.
  14938.  
  14939. Again, all these problems are eased if you use the OffscreenGWorld routines.
  14940.  
  14941. _______________________________________________________________________________
  14942.  
  14943. æKY Copying…PixMap…Records
  14944. æC »Copying PixMap Records                                                 Color QuickDraw
  14945. _______________________________________________________________________________
  14946.  
  14947. PixMap records are copied using the current GDevice record (pointed to by the
  14948. TheGDevice global variable) to determine the destination color information.
  14949. Consequently, whenever copying to an offscreen PixMap record with
  14950. characteristics differing from those of the current GDevice record (which is
  14951. usually the main screen), you should create an appropriate offscreen graphic
  14952. device record and set it as the current graphic device record before the copy.
  14953. If an offscreen PixMap record is only copied from, then no offscreen graphic
  14954. device record is needed since Color QuickDraw obtains the source color
  14955. information from the source PixMap record. (See the Graphic Devices Manager
  14956. chapter for information about offscreen graphics routines and data structures.)
  14957. _______________________________________________________________________________
  14958.  
  14959. æKY Dithering
  14960. æC »Dithering                                                              Color QuickDraw
  14961. _______________________________________________________________________________
  14962.  
  14963. The CopyBits procedure now provides a new dither copy mode.
  14964.  
  14965. Copying using CopyBits from any PixMap record to an indexed device works in one
  14966. of two ways:  
  14967.  
  14968.   •   If the transfer mode is DitherCopy, then CopyBits does its best to
  14969.       provide error diffusion during the copy operation. As with arithmetic
  14970.       transfer modes, hidden colors are ignored, so that color matching is
  14971.       limited by the resolution of the inverse table for the destination
  14972.       graphics device. (See the discussion of hidden colors in the Inverse
  14973.       Table section of the Color Manager chapter, Inside Macintosh, Volume V.)
  14974.       DitherCopy provides good results for most images, but does have
  14975.       drawbacks. A clipped DitherCopy does not provide pixel-for-pixel
  14976.       equivalence to the same unclipped DitherCopy—thus updates are not
  14977.       equivalent to saving the bits behind, and clipped XOR copies will not
  14978.       perform as erases.
  14979.  
  14980.       Currently, if a color search procedure is present, copy mode is used     
  14981.  
  14982.       instead of dither mode. (This may change in future versions.) 
  14983.  
  14984.   •   If you copy from any PixMap record to an indexed device using the classic
  14985.       copy mode, color mapping is done on a pixel-by-pixel basis—no errors are
  14986.       accumulated and hidden colors are ignored. If a color search procedure is
  14987.       present, it is called on a pixel-by-pixel basis.
  14988.  
  14989. If you copy from any PixMap record to a direct device, dithering is never done,
  14990. since dithering is generally useful only when copying to a destination with a
  14991. lower color resolution than the source. If the destination device is 16-bits or
  14992. 32-bits per pixel, then no error diffusion is performed. You can use dithering
  14993. when copying between indexed PixMap records, such as from an 8-bit pixel depth
  14994. to a 4-bit depth, or between two 8-bit PixMap records with different color
  14995. tables.
  14996.  
  14997. _______________________________________________________________________________
  14998.  
  14999. æKY Resizing…Images
  15000. æC »Resizing Images                                                        Color QuickDraw
  15001. _______________________________________________________________________________
  15002.  
  15003. When copying from direct pixel maps, if the destination rectangle is smaller
  15004. than the source rectangle, Color QuickDraw uses an averaging technique to
  15005. provide destination pixels, maintaining high-quality images when shrinking.
  15006. Pixel averaging is also performed when shrinking indexed images using dither
  15007. copy modes, regardless of the destination.
  15008.  
  15009. _______________________________________________________________________________
  15010.  
  15011. æKY Luminance…Mapping
  15012. æC »Luminance Mapping                                                      Color QuickDraw
  15013. _______________________________________________________________________________
  15014.  
  15015. When the user sets a screen device to a gray-scale mode, Color QuickDraw places
  15016. an evenly spaced set of grays in the device CLUT such that they form a linear
  15017. ramp from white to black. 
  15018.  
  15019. When Color QuickDraw displays a color on a graphics device whose pmTable
  15020. contains only grays (ignoring entries used for animation), it computes the
  15021. luminance of the desired color and uses that to determine the appropriate gray
  15022. value to draw.
  15023.  
  15024. To facilitate the creation of grayscale devices, the GetCTable function has been
  15025. enhanced to recognize additional standard CLUT IDs. As described in Volume V,
  15026. the GetCTable function looks like this:
  15027.  
  15028. FUNCTION GetCTable (ctID: Integer) : CTabHandle;
  15029.  
  15030. The default grayscale CLUT for a given pixel depth can be obtained by calling
  15031. GetCTable with a ctID value of PixelSize +32.
  15032.  
  15033. PixelSize    CLUT ID  Color Table Composition         
  15034.         2         34  black, white, 33% gray, 66% gray
  15035.         4         36  black, 14 shades of gray, white
  15036.         8         40  black, 254 shades of gray, white
  15037.  
  15038. The equivalent default color tables can be obtained by adding 64 to the bit
  15039. depth, as described in the Palette Manager chapter.
  15040.  
  15041. PixelSize  CLUT ID  Color Table Composition         
  15042.         2       66  black, white, 50% gray, highlight 
  15043.         4       68  black, 14 colors including a highlight, white
  15044.         8       72  black, 254 colors including a highlight, white
  15045. _______________________________________________________________________________
  15046.  
  15047. æKY Image…Resolution
  15048. æC »Image Resolution                                                       Color QuickDraw
  15049. _______________________________________________________________________________
  15050.  
  15051. Color QuickDraw supports pixel maps of resolutions other than 72 dots per inch 
  15052. (dpi). In the past, applications have accepted pixel maps of a certain number of
  15053. rows and columns and assumed that they were generated on a 72 dpi device. Such
  15054. pixel maps were usually copied and printed at a 72 dpi resolution, lending the
  15055. impression that QuickDraw could not handle pixel maps of higher density. 
  15056.  
  15057. With the advent of frame grabbers and scanners, many pixel maps have resolutions
  15058. of 150, 200, 300 dpi, or greater. A user expects pixel maps to display an
  15059. approximation of the information on a 72 dpi display but print on a higher
  15060. resolution device to the best of the device's ability.
  15061.  
  15062. _______________________________________________________________________________
  15063.  
  15064. æKY Importing…PixMap…Records
  15065. æC »Importing PixMap Records                                               Color QuickDraw
  15066. _______________________________________________________________________________
  15067.  
  15068. The resolution of a PixMap record is contained in the hRes and vRes fields.
  15069. These values are fixed point numbers in dots per inch. When importing pictures,
  15070. applications should check the picture type to see if it was created with
  15071. OpenCPicture.
  15072.  
  15073. An alternative is to replace the StdBits bottleneck during playback. When the
  15074. bottleneck procedure is called, you should
  15075.  
  15076. 1.  check to guarantee that the source is a PixMap record by checking the high
  15077. bit of the PMVersion(rowBytes) field
  15078.  
  15079. 2.  read the hRes and vRes information out of the source PixMap record
  15080.  
  15081. At this point, the source rect field indicates the size of the source in pixels
  15082. at the resolution specified by the hRes and vRes fields. To display it at
  15083. another resolution, your application should compute the dest rect field value
  15084. appropriately. For example if the source resolution is 300 dpi and the intention
  15085. is to display it at 75 dpi, then the destination rectangle width and height
  15086. should be computed as 1/4 of that of the source.  
  15087. _______________________________________________________________________________
  15088.  
  15089. æKY Exporting…PixMap…Records
  15090. æC »Exporting PixMap Records                                               Color QuickDraw
  15091. _______________________________________________________________________________
  15092.  
  15093. When exporting PixMap records, your application should ensure that the hRes and
  15094. vRes fields accurately reflect the image data. During picture recording, the
  15095. destination rectangle of the CopyBits call should be appropriate for display at
  15096. 72 dpi. If you want an entire picture to be a different resolution, use the
  15097. OpenCPicture function.
  15098.  
  15099. _______________________________________________________________________________
  15100.  
  15101. æKY Converting…a…Bitmap…to…a…Region
  15102. æC »Converting a Bitmap to a Region                                        Color QuickDraw
  15103. _______________________________________________________________________________
  15104.  
  15105. A new function, BitMapToRegion, converts a bitmap to a region. If you used the
  15106. PaintRgn procedure on the converted region, the resulting region would be the
  15107. same as the bitmap. This procedure may be useful if you want to test the mouse
  15108. for hits against the black pixels in a bitmap, or drag the outline of a bitmap
  15109. using DragGrayRegion.  
  15110. _______________________________________________________________________________
  15111.  
  15112. æKY Checking…that…QuickDraw…is…Done
  15113. æC »Checking that QuickDraw is Done                                        Color QuickDraw
  15114. _______________________________________________________________________________
  15115.  
  15116. A new function, QDDone, checks to see whether QuickDraw drawing operations have
  15117. completed in a grafport.  This is useful if you are executing in an environment
  15118. with a graphics accelerator, where drawing operations may proceed
  15119. asynchronously.  
  15120.  
  15121. _______________________________________________________________________________
  15122.  
  15123. æKY New…Color…Quickdraw…Routines
  15124. æC »NEW COLOR QUICKDRAW ROUTINES                                           Color QuickDraw
  15125. _______________________________________________________________________________
  15126.  
  15127. Since using direct color only requires internal Color QuickDraw changes to
  15128. recognize direct pixel values, no new routines are defined for direct color. 
  15129. _______________________________________________________________________________
  15130.  
  15131. æKY New…QuickDraw…Result…Codes
  15132. æC »New QuickDraw Result Codes                                             Color QuickDraw
  15133. _______________________________________________________________________________
  15134.  
  15135. QuickDraw uses stack space for work buffers. For complex operations such as
  15136. depth conversion, dithering, or image resizing, stack space may not be
  15137. sufficient. Color QuickDraw now attempts to get temporary memory from
  15138. MultiFinder. If that is still not enough, or if MultiFinder is not present,
  15139. Color QuickDraw returns
  15140.  
  15141.   QDErr  -149  Insufficient stack
  15142.  
  15143. One recourse for the application is to divide the operation—for example divide
  15144. the image into left and right halves—and try again. An alternative is to make
  15145. the stack larger.
  15146.  
  15147. While recording drawing operations into an open region the resulting region
  15148. description might overflow the 64 KB limit. Should this happen Color QuickDraw
  15149. will return -147 in QDErr:
  15150.  
  15151.   QDErr  -147  Region too big
  15152.  
  15153. Since the resulting region is potentially corrupt, closeRgn returns an empty
  15154. region if it detects QDErr has been set to -147.
  15155.  
  15156. _______________________________________________________________________________
  15157.  
  15158. æKY Creating…an…Extended…PICT2…Picture
  15159. æC »Creating an Extended PICT2 Picture                                     Color QuickDraw
  15160. _______________________________________________________________________________
  15161.  
  15162. FUNCTION OpenCPicture (newHeader: PICT2Header) : PicHandle;
  15163.  
  15164. OpenCPicture performs the same functions as OpenPicture, except that it creates
  15165. an extended PICT2 format file, with pixel resolution and the best imaging
  15166. rectangle stored in the header.
  15167.  
  15168. You pass a PICT2Header record describing the rectangle that encloses the drawing
  15169. information you supply for the picture, and you pass horizontal and vertical
  15170. resolutions describing the best resolution for displaying the picture in the
  15171. rectangle. The structure of a PICT2Header record is
  15172.  
  15173. PICT2Header = 
  15174. RECORD
  15175.   SrcRect:  Rect    {source rectangle for best display}
  15176.                     {at HRes, VRes resolution}
  15177.   hRes:     Fixed;  {best horizontal resolution}
  15178.   vRes:     Fixed;  {best vertical resolution}
  15179.   version:  word;   {set to -2}
  15180.   reserved: word;   {reserved for future use}
  15181.   END;
  15182.  
  15183. Note that the order the information is recorded in the PICT2 header differs from
  15184. the order in this record.  See the sample PICT2 file in “The Extended PICT2
  15185. Format.” 
  15186.  
  15187. As with OpenPicture, you close the picture using ClosePicture, and draw it using
  15188. DrawPicture.
  15189.  
  15190. _______________________________________________________________________________
  15191.  
  15192. æKY From…Bitmap…to…Region
  15193. æC »From Bitmap to Region                                                  Color QuickDraw
  15194. _______________________________________________________________________________
  15195.  
  15196. FUNCTION BitMapToRegion (region:RGNHandle; bMap:BitMap) : OSErr;
  15197.  
  15198. The region parameter must be a valid region handle created with a NewRgn
  15199. function. The old region contents are lost.
  15200.  
  15201. The bMap parameter may either be a BitMap or PixMap record. If a PixMap record
  15202. is passed, its pixel size (bits per pixel) must be 1. 
  15203.  
  15204. Result codes
  15205.     rgnTooBigErr   -500  BitMap would convert into a region greater 
  15206.                          than 32 KB 
  15207. pixmapTooDeepErr   -148  PixMap record is deeper than 1 bit per pixel
  15208. _______________________________________________________________________________
  15209.  
  15210. æKY Drawing…Completion
  15211. æC »Drawing Completion                                                     Color QuickDraw
  15212. _______________________________________________________________________________
  15213.  
  15214. FUNCTION QDDone (port:GrafPtr) : Boolean;
  15215.  
  15216. The QDDone function returns true if drawing operations have completed in the
  15217. designated port, false if any remain to be executed.  This call may be useful if
  15218. a graphics accelerator is present and operating asynchronously.  You can ensure
  15219. that all drawing has been done and avoid the possibility that new drawing
  15220. operations might be overlaid by previously issued but unexecuted operations.
  15221.  
  15222. _______________________________________________________________________________
  15223.  
  15224. æKY Reporting…Data…Structure…Changes
  15225. æC »Reporting Data Structure Changes                                       Color QuickDraw
  15226. _______________________________________________________________________________
  15227.  
  15228. The following routines can be used to mitigate possible side effects of directly
  15229. changing a CLUT, PixPat, GrafPort, or GDevice data structure.
  15230.  
  15231. PROCEDURE CTabChanged (ctab: CTabHandle);
  15232.  
  15233. Call CTabChanged after modifying the content of a color table. CTabChanged calls
  15234. GetCTSeed to get a new seed for the color table and notifies QuickDraw of the
  15235. change.
  15236.  
  15237. PROCEDURE PixPatChanged (ppat: PixPatHandle);
  15238.  
  15239. Call PixPatChanged after modifying a PixPat data structure or any of its
  15240. substructures (patMap or patData records). PixPatChanged sets the patXValid flag
  15241. to -1 and notifies QuickDraw of the change.
  15242.  
  15243. If your application changes the pmTable field of the pixel pattern’s patMap, it
  15244. should call PixPatChanged. However, if your application changes the content of
  15245. the CLUT referenced by pmTable, it should call CTabChanged as well.
  15246.  
  15247. PROCEDURE PortChanged (port: GrafPtr);
  15248.  
  15249. Call PortChanged after modifying the content of a port or any of its
  15250. substructures. PortChanged notifies QuickDraw of the change.
  15251.  
  15252. None of the PixPat records pointed to by a CGrafPort record should be changed
  15253. directly. Use PenPixPat and BackPixPat instead. However, if your application
  15254. changes the content of one of the PixPat records, it should call PixPatChanged.
  15255.  
  15256. If your application changes the pmTable field of the port’s PixMap, it should
  15257. call PortChanged. However, if your application changes the content of the color
  15258. table referenced by pmTable, it should call CTabChanged as well.
  15259.  
  15260. PROCEDURE GDeviceChanged (gdh: GDHandle);
  15261.  
  15262. Call GDeviceChanged after modifying a gDevice graphics device record or any of
  15263. its substructures. GDeviceChanged notifies QuickDraw of the change.
  15264.  
  15265. If your application changes the pmTable field of the graphics device record’s
  15266. PixMap, it should call GDeviceChanged. However, if your application changes the
  15267. content of the color table referenced by gdPMap, it should call CTabChanged as
  15268. well.
  15269.  
  15270. _______________________________________________________________________________
  15271.  
  15272. æKY The…Extended…PICT2…Format
  15273. æC »THE EXTENDED PICT2 FORMAT                                              Color QuickDraw
  15274. _______________________________________________________________________________
  15275.  
  15276. The PICT2 format presented in the Color QuickDraw chapter of Volume V has been
  15277. extended to allow storing direct PixMaps and for maintaining resolution and
  15278. imaging rectangle information.
  15279.  
  15280.  
  15281. The major differences between version 1 and version 2 pictures are that three
  15282. opcodes previously listed as reserved have been defined, and one defined opcode
  15283. has been redefined:
  15284.  
  15285. Opcode 2C signals font name information.
  15286.  
  15287. Opcodes 9A and 9B now define direct-pixel pictures, with PixMaps containing
  15288. three components, directly specifying RGB values.
  15289.  
  15290. Opcode 0C00 still signifies a header record, and it is still 24 bytes, but the
  15291. contents have changed.
  15292.  
  15293. This section presents a sample PICT file and the extended PICT2 opcodes.
  15294.  
  15295. _______________________________________________________________________________
  15296.  
  15297. æKY Sample…Extended…PICT2…File
  15298. æC »Sample Extended PICT2 File                                             Color QuickDraw
  15299. _______________________________________________________________________________
  15300.  
  15301. An example of an extended PICT2 data file that can display a single direct-pixel
  15302. image is shown in Table 1.
  15303.  
  15304. Table 1. PICT file example
  15305. ________________________________________________________________________
  15306.   Size  Name    Description
  15307.   (in bytes)
  15308.   2  picSize    low word of picture size
  15309.   8  picFrame   rectangular bounding box of picture, at 
  15310.                 72 dpi
  15311.  
  15312. Picture Definition Data:
  15313.  
  15314.   2  version op  version opcode = $0011
  15315.   2  version     version number = $02FF
  15316.   2  Header op   header opcode = $0C00
  15317.   2  version     set to -2 for extended PICT2
  15318.   2  reserved    reserved for future Apple use
  15319.   4  HRes        native horizontal resolution 
  15320.   4  VRes        native vertical resolution 
  15321.   8  SrcRect     native source rectangle
  15322.   4  reserved    reserved for future Apple use
  15323.   2  opbitsRect  bitMap opcode = $009A for direct
  15324.   4  baseAddr    for direct must be $000000FF. See Table 4  
  15325.   2  rowBytes    integer, must have high bit set to signal pixMap
  15326.   8  bounds      rectangle, bounding rectangle at source resolution
  15327.   2  pmVersion   integer, pixMap version number = 0
  15328.   2  packType    integer, defines packing format
  15329.   4  packSize    LongInt, length of pixel data = 0
  15330.   4  hRes        fixed, horizontal resolution (dpi) of source data, 
  15331.                  normally $00480000 (72 dpi)
  15332.   4  vRes        fixed, vertical resolution (dpi) of source data,
  15333.                  normally $00480000 (72 dpi)
  15334.   2  pixelType   integer, defines pixel type; 16 for direct
  15335.   2  pixelSize   integer, number of bits in pixel; 16 or 32 for direct
  15336.   2  cmpCount    integer, number of components in pixel; 3 for direct
  15337.   2  cmpSize     integer, number of bits per component; 5 or 8 for direct
  15338.   4  planeBytes  LongInt, offset to next plane = 0
  15339.      pmTable     color table = 0
  15340.      pmReserved  reserved = 0
  15341.   4  ctSeed      LongInt, color table seed
  15342.   2  ctFlags     integer, flags for color table
  15343.   2  ctSize      integer, number of entries in ctTable –1
  15344.   (ctSize+1) *  8   ctTable  color lookup table data
  15345.   8  srcRect     rectangle, source rectangle at source resolution
  15346.   8  dstRect     rectangle, destination rectangle at 72 dpi resolution 
  15347.   2  mode        integer, transfer mode see Table 5    
  15348.      pixData     pixel data  
  15349.   2  endPICT op  end-of-picture opcode = $00FF
  15350.  
  15351. _______________________________________________________________________________
  15352.  
  15353. æKY PICT2…Opcode…Types
  15354. æC »PICT2 Opcode Types                                                     Color QuickDraw
  15355. _______________________________________________________________________________
  15356.  
  15357. The following description shows the new PICT2 format, with changes from the
  15358. description in Volume V indicated by an asterisk.
  15359.  
  15360.  
  15361. The opcode information in Table 3x is provided for the purpose of debugging
  15362. application-generated PICT files. Your application should generate and read PICT
  15363. files only by using standard QuickDraw or Color QuickDraw routines (OpenPicture,
  15364. OpenCPicture, ClosePicture).  The data types listed in Table 2x are used in the
  15365. Table 3x opcode definitions. 
  15366.  
  15367. Table 2.  Data types
  15368. ________________________________________________________________________
  15369. Type          Size
  15370. v1 opcode     1 byte
  15371. v2 opcode     2 bytes
  15372. integer       2 bytes
  15373. long integer  4 bytes
  15374. mode          2 bytes
  15375. point         4 bytes
  15376. 0..255        1 byte
  15377. –128..127     1 byte (signed)
  15378. rect          8 bytes (top, left, bottom, right: integer)
  15379. poly         10+ bytes
  15380. region       10+ bytes
  15381. fixed-point number  4 bytes
  15382. pattern       8 bytes
  15383. rowbytes      2 bytes (always an even quantity)
  15384. ________________________________________________________________________
  15385.  
  15386. _______________________________________________________________________________
  15387.  
  15388. æKY Extended…PICT2…Opcodes
  15389. æC »Extended PICT2 Opcodes                                                 Color QuickDraw
  15390. _______________________________________________________________________________
  15391.  
  15392. Valid picture opcodes are listed in Table 3.  New opcodes or those altered to
  15393. extend the PICT2 format are indicated by a leading asterisk (*). The unused
  15394. opcodes found throughout the table are reserved for Apple use. The length of the
  15395. data that follows these opcodes is pre-defined, so if they are encountered in
  15396. pictures, they can simply be skipped. By default, QuickDraw reads and then
  15397. ignores these opcodes.
  15398.  
  15399.  
  15400.  
  15401. Table 3.  PICT opcodes
  15402. ________________________________________________________________________
  15403. Opcode Name            Description                           Data Size
  15404.                                                              (in bytes)
  15405. $0000  NOP             nop                                   0
  15406. $0001  Clip            clip                                  region size + data
  15407. $0002  BkPat           background pattern                    8
  15408. $0003  TxFont          text font (word)                      2
  15409. $0004  TxFace          text face (byte)                      1
  15410. $0005  TxMode          text mode (word)                      2
  15411. $0006  SpExtra         space extra (fixed point)             4
  15412. $0007  PnSize          pen size (point)                      4
  15413. $0008  PnMode          pen mode (word)                       2
  15414. $0009  PnPat           pen pattern                           8
  15415. $000A  FillPat         fill pattern                          8
  15416. $000B  OvSize          oval size (point)                     4
  15417. $000C  Origin          dh, dv (word)                         4
  15418. $000D  TxSize          text size (word)                      2
  15419. $000E  FgColor         foreground color (long)               4
  15420. $000F  BkColor         background color (long)               4
  15421. $0010  TxRatio         numer (point), denom (point)          8
  15422. $0011  Version         version (byte)                        1
  15423. $0012  BkPixPat        color background pattern              variable:
  15424.                                                              see Table 4
  15425. $0013  PnPixPat        color pen pattern                     variable:
  15426.                                                              see Table 4
  15427. $0014  FillPixPat      color fill pattern                    variable:
  15428.                                                              see Table 4
  15429. $0015  PnLocHFrac      fractional pen position               2
  15430. $0016  ChExtra         extra for each character              2
  15431. $0017  reserved        opcode                                0
  15432. $0018  reserved        opcode                                0
  15433. $0019  reserved        opcode                                0
  15434. $001A  RGBFgCol        RGB foreColor                         variable:
  15435.                                                              see Table 4
  15436. $001B  RGBBkCol        RGB backColor                         variable:
  15437.                                                              see Table 4
  15438. $001C  HiliteMode      hilite mode flag                      0
  15439. $001D  HiliteColor     RGB hilite color                      variable:
  15440.                                                              see Table 4
  15441. $001E  DefHilite       Use default hilite color              0
  15442. $001F  OpColor         RGB OpColor for                       variable:
  15443.                        arithmetic modes                      see Table 4
  15444. $0020  Line            pnLoc (point), newPt (point)          8
  15445. $0021  LineFrom        newPt (point)                         4
  15446. $0022  ShortLine       pnLoc (point, dh, dv                  6
  15447.                        (-128..127)
  15448. $0023  ShortLineFrom   dh, dv (-128..127)                    2
  15449. $0024  reserved        opcode + 2 bytes data                 2+ data
  15450.                        length + data                         length
  15451. $0025  reserved        opcode + 2 bytes data                 2+ data
  15452.                        length + data                         length       
  15453. $0026  reserved        opcode + 2 bytes data                 2+ data
  15454.                        length + data                         length
  15455. $0027  reserved        opcode + 2 bytes data                 2+ data
  15456.                        length + data                         length
  15457. $0028  LongText        txLoc (point), count                  5 + text
  15458.                        (0..255), text
  15459. $0029  DHText          dh (0..255), count                    2 + text
  15460.                        (0..255), text
  15461. $002A  DVText          dv (0..255), count                    2 + text
  15462.                        (0..255), text
  15463. $002B  DHDVText        dh, dv (0..255), count                3 + text
  15464.                        (0..255), text
  15465. $002C  *fontName       data length (word), old font          5+ name
  15466.                        ID (word), name length (byte),        length
  15467.                        font name 
  15468. $002D  reserved        opcode + 2 bytes data                 2+ data    
  15469.                        length + data                         length
  15470. $002E  reserved        opcode + 2 bytes data                 2+ data
  15471.                        length + data                         length
  15472. $002F  reserved        opcode + 2 bytes data                 2+ data
  15473.                        length + datalength
  15474. $0030  frameRect       rect                                  8
  15475. $0031  paintRect       rect                                  8
  15476. $0032  eraseRect       rect                                  8
  15477. $0033  invertRect      rect                                  8
  15478. $0034  fillRect        rect                                  8
  15479. $0035  reserved        opcode + 8 bytes data                 8
  15480. $0036  reserved        opcode + 8 bytes data                 8
  15481. $0037  reserved        opcode + 8 bytes data                 8
  15482. $0038  frameSameRect   rect                                  0
  15483. $0039  paintSameRect   rect                                  0
  15484. $003A  eraseSameRect   rect                                  0
  15485. $003B  invertSameRect  rect                                  0
  15486. $003C  fillSameRect    rectangle                             0
  15487. $003D  reserved        opcode                                0
  15488. $003E  reserved        opcode                                0
  15489. $003F  reserved        opcode                                0
  15490. $0040  frameRRect      rect (see Note # 5 )                  8
  15491. $0041  paintRRect      rect (see Note # 5 )                  8
  15492. $0042  eraseRRect      rect (see Note # 5 )                  8
  15493. $0043  invertRRec      rect (see Note # 5 )                  8
  15494. $0044  fillRRect       rect (see Note # 5 )                  8
  15495. $0045  reserved        opcode + 8 bytes data                 8
  15496. $0046  reserved        opcode + 8 bytes data                 8
  15497. $0047  reserved        opcode + 8 bytes data                 8
  15498. $0048  frameSameRRect  rect                                  0
  15499. $0049  paintSameRRect  rect                                  0
  15500. $004A  eraseSameRRect  rect                                  0
  15501. $004B  invertSameRRect rect                                  0
  15502. $004C  fillSameRRect   rect                                  0
  15503. $004D  reserved        opcode                                0
  15504. $004E  reserved        opcode                                0
  15505. $004F  reserved        opcode                                0
  15506. $0050  frameOval       rect                                  8
  15507. $0051  paintOval       rect                                  8
  15508. $0052  eraseOval       rect                                  8
  15509. $0053  invertOval      rect                                  8
  15510. $0054  fillOval        rect                                  8
  15511. $0055  reserved        opcode + 8 bytes data                 8
  15512. $0056  reserved        opcode + 8 bytes data                 8
  15513. $0057  reserved        opcode + 8 bytes data                 8
  15514. $0058  frameSameOval   rect                                  0
  15515. $0059  paintSameOval   rect                                  0
  15516. $005A  eraseSameOval   rect                                  0
  15517. $005B  invertSameOval  rect                                  0
  15518. $005C  fillSameOval    rect                                  0
  15519. $005D  reserved        opcode                                0
  15520. $005E  reserved        opcode                                0
  15521. $005F  reserved        opcode                                0
  15522. $0060  frameArc        rect, startAngle, arcAngle            12
  15523. $0061  paintArc        rect, startAngle, arcAngle            12
  15524. $0062  eraseArc        rect, startAngle, arcAngle            12
  15525. $0063  invertArc       rect, startAngle, arcAngle            12
  15526. $0064  fillArc         rect, startAngle, arcAngle            12
  15527. $0065  reserved        opcode + 12 bytes                     12
  15528. $0066  reserved        opcode + 12 bytes                     12
  15529. $0067  reserved        opcode + 12 bytes                     12
  15530. $0068  frameSameArc    rect                                  4
  15531. $0069  paintSameArc    rect                                  4
  15532. $006A  eraseSameArc    rect                                  4
  15533. $006B  invertSameAr    rect                                  4
  15534. $006C  fillSameArc     rect                                  4
  15535. $006D  reserved        opcode + 4 bytes                      4
  15536. $006E  reserved        opcode + 4 bytes                      4
  15537. $006F  reserved        opcode + 4 bytes                      4
  15538. $0070  framePoly       poly                                  polygon size
  15539. $0071  paintPoly       poly                                  polygon size
  15540. $0072  erasePoly       poly                                  polygon size
  15541. $0073  invertPoly      poly                                  polygon size
  15542. $0074  fillPoly        poly                                  polygon size
  15543. $0075  reserved        opcode + poly
  15544. $0076  reserved        opcode + poly
  15545. $0077  reserved        opcode word + poly
  15546. $0078  frameSamePoly   (not yet implemented:                 0 
  15547.                         same as 70, etc)
  15548. $0079  paintSamePoly   (not yet implemented)                 0
  15549. $007A  eraseSamePoly   (not yet implemented)                 0
  15550. $007B  invertSamePoly  (not yet implemented)                 0
  15551. $007C  fillSamePoly    (not yet implemented)                 0
  15552. $007D  reserved        opcode                                0
  15553. $007E  reserved        opcode                                0
  15554. $007F  reserved        opcode                                0
  15555. $0080  frameRgn        rgn                                   region size
  15556. $0081  paintRgn        rgn                                   region size
  15557. $0082  eraseRgn        rgn                                   region size
  15558. $0083  invertRgn       rgn                                   region size
  15559. $0084  fillRgn         rgn                                   region size
  15560. $0085  reserved        opcode + rgn                          region size
  15561. $0086  reserved        opcode + rgn                          region size
  15562. $0087  reserved        opcode + rgn                          region size
  15563. $0088  frameSameRgn    (not yet implemented- 0 same as 80, etc.)
  15564. $0089  paintSameRgn    (not yet implemented)                 0
  15565. $008A  eraseSameRgn    (not yet implemented)                 0
  15566. $008B  invertSameRgn   (not yet implemented)                 0
  15567. $008C  fillSameRgn     (not yet implemented)                 0
  15568. $008D  reserved        opcode                                0
  15569. $008E  reserved        opcode                                0
  15570. $008F  reserved        opcode                                0
  15571. $0090  BitsRect        copybits, rect clipped                variable: 
  15572.                                                              see Table 4
  15573. $0091  BitsRgn         copybits, rgn clipped                 variable: 
  15574.                                                              see Table 4
  15575. $0092  reserved        opcode + 2 bytes data                 2+ data
  15576.                        length + data                         length
  15577. $0093  reserved        opcode + 2 bytes data                 2+ data
  15578.                        length + data                         length
  15579. $0094  reserved        opcode + 2 bytes data                 2+ data
  15580.                        length + data                         length
  15581. $0095  reserved        opcode + 2 bytes data                 2+ data
  15582.                        length + data                         length
  15583. $0096  reserved        opcode + 2 bytes data                 2+ data
  15584.                        length + data                         length
  15585. $0097  reserved        opcode + 2 bytes data                 2+ data
  15586.                        length + data                         length
  15587. $0098  PackBitsRect    packed copybits, rect                 variable:         
  15588.                        clipped                               see Table 4
  15589. $0099  PackBitsRgn     packed copybits, rect                 variable:         
  15590.                        clipped                               see Table 4
  15591. $009A  *DirectBitsRect PixMap, srcRect, dstRect, mode        variable
  15592.                        (Word), PixData                       see Table 4
  15593. $009B  *DirectBitsRgn  PixMap, srcRect, dstRect, mode        variable
  15594.                        (Word), maskRgn, PixData              see Table 4
  15595. $009C  reserved        opcode + 2 bytes data                 2+ data
  15596.                        length + data                         length
  15597. $009D  reserved        opcode + 2 bytes data                 2+ data
  15598.                        length + data                         length
  15599. $009E  reserved        opcode + 2 bytes data                 2+ data
  15600.                        length + data                         length
  15601. $009F  reserved        opcode + 2 bytes data                 2+ data
  15602.                        length + data                         length
  15603. $00A0  ShortComment    kind (word)                           2
  15604. $00A1  LongComment     kind (word), size                     4+data
  15605.                        (word), data
  15606. $00A2  reserved        opcode + 2 bytes data                 2+ data
  15607.                        length + data                         length
  15608. :      :               :                                     
  15609. :      :               :
  15610. $00AF  reserved        opcode + 2 bytes data                 2+ data 
  15611.                        length + data                         length
  15612. $00B0  reserved        opcode                                0
  15613. :      :               :                                     
  15614. :      :               :
  15615. $00CF  reserved        opcode                                0
  15616. $00D0  reserved        opcode + 4 bytes data                 4+ data
  15617.                        length + data                         length
  15618. :      :               :
  15619.  
  15620. :      :               :
  15621.  
  15622. $00FE  reserved        opcode + 4 bytes data                 4+ data
  15623.                        length + data                         length
  15624. $00FF  opEndPic        end of picture                        2
  15625. $0100  reserved        opcode + 2 bytes data                 2
  15626. :      :               :
  15627. :      :               :
  15628.  
  15629. $01FF  reserved        opcode + 2 bytes data                 2
  15630. $0200  reserved        opcode + 4 bytes data                 4
  15631. :      :               :
  15632.  
  15633. $0BFF  reserved        opcode + 4 bytes data                 22
  15634. $0C00  *HeaderOp       Version (word), reserved              24
  15635.                        (word), Hres, VRes (Fixed),  
  15636.                        SrcRect (Rect), reserved (Long)
  15637. $0C01  reserved        opcode + 4 bytes data                 24
  15638. :      :               :
  15639.  
  15640. $7F00  reserved        opcode + 254 bytes data               254
  15641. :      :               :
  15642.  
  15643. $7FFF  reserved        opcode + 254 bytes data               254
  15644. $8000  reserved        opcode                                0
  15645. :      :               :
  15646.  
  15647. $80FF  reserved        opcode                                0
  15648. $8100  reserved        opcode + 4 bytes data                 4+ data
  15649.                        length + data                         length
  15650. :      :               :
  15651.  
  15652. $FFFF  reserved        opcode + 4 bytes data                 4+ data
  15653.                        length + data                         length
  15654. ________________________________________________________________________
  15655.  
  15656. Notes to Table 3
  15657.  
  15658. 1. Remember, opcode size is 1 byte for PICT, 2 bytes for PICT2.
  15659.  
  15660. 2. Because opcodes must be word aligned in version 2 pictures, a byte of 0 
  15661. (zero) data is added after odd-size data.
  15662.  
  15663. 3. The size of reserved opcodes has been defined. They can occur only in version
  15664. 2 pictures.
  15665.  
  15666. 4. All unused opcodes are reserved for future Apple use and should not be used.
  15667.  
  15668. 5. For opcodes $0040–$0044: rounded-corner rectangles use the setting of the
  15669. ovSize point (refer to opcode $000B)
  15670. 6. For opcodes $0090 and $0091: data is unpacked. These opcodes can only be used
  15671. for rowbytes less than 8.
  15672.  
  15673. 7. For opcodes $0100–$7FFF: the amount of data for opcode $nnXX = 2 * nn bytes.
  15674.  
  15675.  
  15676.  
  15677. The New Opcodes: Expanded Format
  15678.  
  15679. The expanded format of the version 2 PICT opcodes is shown in Table 4 below. 
  15680.  
  15681. Table 4. Data Format of Version 2 PICT Opcodes 
  15682. ________________________________________________________________________
  15683. Opcode Name            Description                    Reference           
  15684.                                                       to Notes
  15685.  
  15686. $002C  fontName        ID and name of font             See Note 1
  15687. $009A  DirectBitsRect  PixMap, src and dst             See Note 2
  15688.                        rects, mode, and PixData
  15689. $009B  DirectBitsRgn   PixMap, src and dst             See Note 2
  15690.                        rects, mode, maskRgn,
  15691.                        PixData
  15692. $0C00  HeaderOp        Version (Word), reserved Word,  See Note 3
  15693.                        Hres, VRes (Fixed), SrcRect 
  15694.                        (Rect), reserved (Word)
  15695.  
  15696. ________________________________________________________________________
  15697.  
  15698. Notes to Table 4
  15699.  
  15700. 1. The fontName information begins with a word containing the field’s data
  15701. length, followed by a word containing the old font ID, a byte containing the
  15702. length of the font name, and the font name itself.
  15703.  
  15704.  
  15705. 2. Unlike previous Bits opcodes, the DirectBits opcodes store the baseAddr field
  15706. of the pixMap structure in a PICT2. For compatibility with existing systems the
  15707. baseAddr field is set to $000000FF. On systems without direct pixel support,
  15708. opcodes $009A and $009B read a word from the picture and then skip that much
  15709. data. The next opcode fetched from the picture is $00FF, which terminates
  15710. picture playback.
  15711.  
  15712.  
  15713. The DirectBitsRect opcode will be followed by this structure:
  15714.  
  15715.  
  15716.   pixMap:           { described below } 
  15717.   srcRect:   Rect;  { source rectangle } 
  15718.   dstRect:   Rect;  { destination rectangle } 
  15719.   mode:      word;  { transfer mode }  
  15720.   pixData:          { described below }
  15721.  
  15722. The DirectBitsRgn opcode will be followed by this structure:
  15723.  
  15724.  
  15725.   pixMap:           { described below }  
  15726.   srcRect:  Rect;   { source rectangle }  
  15727.   dstRect:  Rect;   { destination rectangle }  
  15728.   mode:     word;   { transfer mode }   
  15729.   maskRgn:  Region; { region for masking }  
  15730.   pixData:          { described below }
  15731.  
  15732. The following pseudocode describes the pixData data type.
  15733.  
  15734.  
  15735. pixData:  
  15736.  
  15737.   If packType = 1 (unpacked) or rowbytes < 8 then data is unpacked, and
  15738.     data size = rowBytes * (bounds.bottom-bounds.top);
  15739.  
  15740.   If packType = 2 (drop pad byte) then the high-order pad byte of a     
  15741.     32-bit direct pixel is dropped, and
  15742.     data size = (3/4) * rowBytes * (bounds.bottom-bounds.top);
  15743.  
  15744.   If packType > 2 (packed) then 
  15745.     Image contains (bounds.bottom-bounds.top) packed scanlines
  15746.     Each scanline consists of [byteCount] [data].
  15747.     If rowBytes > 250 then byteCount is a word, else it is a byte.
  15748.  
  15749. In a picture, the packType field of a pixMap specifies the manner in which the
  15750. pixData was compressed.  To facilitate banding of images when memory is short,
  15751. all data compression is done on a scanline basis. The currently defined packing
  15752. schemes are:
  15753.   
  15754. 1 = no packing
  15755.  
  15756. 2 = remove pad byte—supported only for 32-bit pixels (24-bit data)
  15757.  
  15758. 3 = run length encoding by pixelSize chunks, one scanline at a time—supported
  15759. only for 16-bit pixels
  15760.  
  15761. 4 = run length encoding all of one component at a time, one scanline at a time,
  15762. red component first—supported only for 32-bit pixels (24-bit data)
  15763.  
  15764. For future compatibility, other packType values skip scanline data and draw
  15765. nothing. Since pixMap data in memory is assumed to be unpacked regardless of the
  15766. packType field value, packType can be used to tell the picture-recording
  15767. mechanism what packing technique to use on that data. A packType value of zero
  15768. in memory indicates that the default packing scheme should be used. As a general
  15769. rule, using the default packing scheme is recommended. Currently, the default
  15770. packType for pixelSize=16 is scheme 3, for pixelSize=32 it is scheme 4.
  15771. Regardless of the setting of packType at the time of picture recording, the
  15772. packType actually used to save the image will be recorded in the picture.
  15773.  
  15774. Since each scanline of packed data is preceded by a byte count, packSize is not
  15775. used and must be zero for future compatibility.
  15776.  
  15777. When the pixel type is direct chunky, cmpCount * cmpSize ≤ pixelSize.  For
  15778. storing 24 bit data in a 32 bit pixel, cmpSize would be eight and cmpCount would
  15779. be three.  If you set cmpCount = 4 then the high byte will be compressed by
  15780. packing scheme 4 and stored in the picture.
  15781.  
  15782. 3. The headerOp information is passed to the OpenCPicture routine as a
  15783. PictureHeader record, which has the structure:
  15784.  
  15785. TYPE
  15786.   PictureHeader = Record
  15787.     version:   word;
  15788.     reserved:  word;
  15789.     HRes:      Fixed;
  15790.     VRes:      Fixed;
  15791.     SrcRect:   Rect
  15792.     END;
  15793.  
  15794.  
  15795. _______________________________________________________________________________
  15796.  
  15797. æKY Summary…of…Color…Quickdraw…Vol…VI…Changes
  15798. æC »SUMMARY OF COLOR QUICKDRAW CHANGES                                     Color QuickDraw
  15799. _______________________________________________________________________________
  15800.  
  15801. The following cards summarize the constants, data types, and routines for Color
  15802. Quickdraw.
  15803. _______________________________________________________________________________
  15804.  
  15805. æKY Color…Quickdraw…Constants
  15806. æC »Constants                                                              Color QuickDraw
  15807. _______________________________________________________________________________
  15808.  
  15809. CONST
  15810.  
  15811. {New Constants for Color QuickDraw}
  15812.  
  15813. ditherCopy  = 64;  {Dither mode for Copybits}
  15814. RGBDirect   = 16;  {16 & 32 bits/pixel pixelType value}
  15815. _______________________________________________________________________________
  15816.  
  15817. æKY Color…Quickdraw…Data…Types
  15818. æC »Data Types                                                             Color QuickDraw
  15819. _______________________________________________________________________________
  15820.  
  15821. PICT2Header = 
  15822. RECORD
  15823.   version:   word;   {set to -2}
  15824.   reserved:  word;   {reserved for future use}
  15825.   hRes:      Fixed;  {best horizontal resolution}
  15826.   vRes:      Fixed;  {best vertical resolution}
  15827.   SrcRect:   Rect    {source rectangle for best display}
  15828.                      {at hRes, vRes resolution}
  15829.   END;
  15830. _______________________________________________________________________________
  15831.  
  15832. æKY Color…Quickdraw…Vol…VI…Routines
  15833. æC »Routines                                                               Color QuickDraw
  15834. _______________________________________________________________________________
  15835.  
  15836. FUNCTION OpenCPicture  (newHeader: PICT2Header) : PicHandle;
  15837. FUNCTION GetCTable  (ctID: Integer) : CTabHandle;
  15838. FUNCTION BitMapToRegion  (region:RGNHandle; bMap:BitMap) : OSErr;
  15839. PROCEDURE CTabChanged  (ctab: CTabHandle);
  15840. PROCEDURE PixPatChanged  (ppat: PixPatHandle);
  15841. PROCEDURE GDeviceChanged  (gdh: GDHandle);
  15842. FUNCTION QDDone (port:GrafPtr) : Boolean;
  15843. _______________________________________________________________________________
  15844.  
  15845. æKY Color…Quickdraw…Result…Codes
  15846. æC »Result Codes                                                           Color QuickDraw
  15847. _______________________________________________________________________________
  15848.  
  15849. QDErr              -147  Region too big
  15850. pixmapTooDeepErr   -148  PixMap record is deeper than 1 bit per pixel
  15851. QDErr              -149  Insufficient stack
  15852. rgnTooBigErr       -500  BitMap would convert into a region greater than 32 KB 
  15853. _______________________________________________________________________________
  15854.  
  15855.  
  15856.  
  15857.  
  15858. æKY About…The…ColorQuickDraw…Chapter
  15859. æC »ABOUT THIS CHAPTER                                         ColorQuickDraw
  15860. _______________________________________________________________________________
  15861.  
  15862. Warning:  This chapter has not been updated to reflect changes and improvements
  15863.           that are available on systems using 32-Bit QuickDraw.  For further
  15864.           information on 32-Bit QuickDraw, please refer to the 32-Bit QuickDraw
  15865.           documentation (available on “Phil & Dave’s Excellent CD: The Release
  15866.           Version).
  15867.  
  15868. A new version of QuickDraw has been created to take advantage of the capabilities of
  15869. the Macintosh II. Color QuickDraw is able to use a very large number of colors and
  15870. can take advantage of systems that have one or more screens of any size. This chapter
  15871. describes the use of color with one screen. The following chapter, “Graphics Devices”,
  15872. explains what your program should do to support more than one screen.
  15873.  
  15874. The features of Color QuickDraw implemented for the Macintosh Plus, the Macintosh SE,
  15875. and the Macintosh II are
  15876.  
  15877.   •  Text drawing modes are enhanced, and now include a text mask mode,
  15878.      drawing with multibit fonts, and fractional character positioning.
  15879.   •  The QuickDraw picture format (PICT) has been enhanced, and includes
  15880.      a number of new opcodes.
  15881.  
  15882. Some of the features of Color QuickDraw for the Macintosh II are
  15883.  
  15884.   •  All drawing operations supported by old QuickDraw can now be
  15885.      performed in color.
  15886.   •  Color QuickDraw supports the use of as many as 2^48 colors; however,
  15887.      current hardware can only support 2^24 colors, and this assumes the
  15888.      presence of 32-Bit QuickDraw.  In addition, Color QuickDraw’s color
  15889.      model is hardware-independent, allowing programs to operate
  15890.      independently of the display device.
  15891.   •  Color QuickDraw includes several new data types: color tables,
  15892.      color icons, color patterns, and color cursors. These types can
  15893.      be stored as resources that are easily used by your program.
  15894.   •  A new set of transfer modes has been added. These modes allow colors
  15895.      to be blended with or added to the colors that are already on the screen.
  15896.   •  Most Toolbox Managers have been enhanced to use color. Thus you can
  15897.      now add color to windows, menus, controls, dialog boxes, and TextEdit
  15898.      text. Refer to the appropriate chapters for more information.
  15899.   •  The QuickDraw picture format (PICT) has been extended so that Color
  15900.      QuickDraw images can be recorded in pictures.
  15901.  
  15902. This chapter introduces the basic concepts, terminology, and data structures underlying
  15903. the Macintosh II approach to graphics. The material presented here assumes familiarity
  15904. with the QuickDraw concepts described in the QuickDraw chapter, such as bit maps,
  15905. graphics ports, patterns, cursors, and transfer modes. You should also be familiar
  15906. with the use of resources, as presented in the Resource Manager chapter.
  15907.  
  15908. _______________________________________________________________________________
  15909.  
  15910.  
  15911. æKY Color…Representation
  15912. æC »COLOR REPRESENTATION                                       ColorQuickDraw
  15913. _______________________________________________________________________________
  15914.  
  15915. The following sections introduce the basic concepts and terminology used in Color
  15916. QuickDraw. It’s important to keep in mind that Color QuickDraw is designed to be
  15917. device-independent. The range of colors available is the result of the system configuration:
  15918. the screen resolution, the graphics hardware used to produce color, and the software
  15919. used to select and store color values. Color QuickDraw provides a consistent way of
  15920. dealing with color, regardless of the characteristics of the video card or display
  15921. device.
  15922.  
  15923. The original QuickDraw represents each dot on the screen (known as a pixel) as a
  15924. single bit in memory. Each bit can have two values, zero or one. This allows two
  15925. colors, usually black and white, to be displayed.
  15926.  
  15927. To produce color graphics, more than one bit of memory per pixel displayed is needed.
  15928. If two bits per pixel are available, four colors can be displayed. Four bits per
  15929. pixel provides a display of 16 colors, and eight bits per pixel provides a display of
  15930. 256 colors. The bits in a pixel, taken together, form a number known as the pixel
  15931. value.
  15932.  
  15933. The number of possible colors is related to the amount of memory used to store each
  15934. pixel. Since displayed pixels are stored in RAM on the video card, rather than in the
  15935. RAM in the Macintosh, the quality of the graphics depends on capabilities of the
  15936. video card used.
  15937.  
  15938. _______________________________________________________________________________
  15939.  
  15940. »RGB Space
  15941.  
  15942. Color QuickDraw represents colors in RGB space. Each color has a red, a green, and a
  15943. blue component, hence the name RGB. These components may be visualized as being
  15944. mapped into a color cube, as shown in Figures 1 and 2. (Figure 1 is a color representation
  15945. of Figure 2.)
  15946.  
  15947. •••Refer to Figure 1.•••
  15948.  
  15949. Figure 1–RGB Color Cube (Color Version)
  15950.  
  15951. •••Refer to Figure 2.•••
  15952.  
  15953. Figure 2–RGB Color Cube (B/W Version)
  15954.  
  15955. The data structures used within Color Quickdraw express each RGB component as an
  15956. unsigned integer value. Each R, G, and B can have a value from $0000 to $FFFF (or 0
  15957. to 65,535). RGB color is additive; that is, as the value of a component is increased,
  15958. the amount of that component in the total color increases. An RGB color is black if
  15959. all three components are set to 0, or white if each component is set to 65,535. Pixel
  15960. values between these two extremes can be combined to represent all the possible
  15961. colors. For instance, pixel values that lie along the diagonal between black and
  15962. white, and for which R = G = B, are all perceived as shades of gray.
  15963.  
  15964. _______________________________________________________________________________
  15965.  
  15966. »Other Color Spaces
  15967.  
  15968. In addition to RGB, several other color models are commonly used to represent colors.
  15969. These other models include HSV (hue, saturation, value), HLS (hue, lightness, saturation),
  15970. and CMY (cyan, magenta, yellow). If you wish to work in a different color space in
  15971. your program, you can use the conversion routines provided in the Color Picker Package
  15972. to convert colors to their RGB equivalents before passing them to Color QuickDraw.
  15973. Please refer to the Color Picker Package chapter for more details.
  15974.  
  15975. _______________________________________________________________________________
  15976.  
  15977.  
  15978. æKY Using…Color…on…the…Macintosh…II
  15979. æC »USING COLOR ON THE MACINTOSH II                            ColorQuickDraw
  15980. _______________________________________________________________________________
  15981.  
  15982. Before you read about the details of how to use Color QuickDraw, it’s useful to
  15983. understand the various components of the color system and how they interact with each
  15984. other. This section, through a series of rules and examples, attempts to illustrate
  15985. these interactions.
  15986.  
  15987. Rule 1: The user selects the depth of the screen using the Control Panel.
  15988.  
  15989. This rule is mentioned first to convey the fundamental need for device independence.
  15990. Your application shouldn’t change the depth of the screen, because it must avoid
  15991. conflicts with desk accessories or other applications that are using the screen at
  15992. the same time. Let the user decide how many colors should be displayed.
  15993.  
  15994. Rule 2: Work with colors in RGB space, not with the colors on the screen.
  15995.  
  15996. Whenever possible, your application should assume that it’s drawing to a screen that
  15997. has 2^48 colors. Let Color QuickDraw determine what colors to actually display on the
  15998. screen. This lets your program work better when drawing to devices that support more
  15999. colors.
  16000.  
  16001. The easiest way to follow this rule is for a program to call the Color Picker Package
  16002. to select colors. The Color Picker returns an RGB value, which can then be used as
  16003. the current color. When Color QuickDraw draws using that color, it selects the color
  16004. that best matches the specified RGB.
  16005.  
  16006. Rule 3: To ensure good color matching, and to avoid conflict with other applications
  16007. and desk accessories, use the Palette Manager.
  16008.  
  16009. If your program requires a very specific set of colors not found in the default
  16010. selection of colors, for instance 128 levels of gray, then you should use the Palette
  16011. Manager. The Palette Manager lets you specify the set of colors that is to be used by
  16012. a particular window. When that window is brought to the front, its set of colors is
  16013. switched in (with a minimal amount of impact on the rest of the screen).
  16014.  
  16015. You should also use the Palette Manager if your application needs to animate colors
  16016. (that is, to change the colors of pixels that are already displayed).
  16017.  
  16018. The Palette Manager is a powerful tool because it makes sure that your application
  16019. gets the best selection of colors across multiple screen devices and multiple screen
  16020. depths. You don’t have to worry about interactions with desk accessories or other
  16021. applications. Please refer to the chapter on the Palette Manager for more information
  16022. on using the Palette Manager routines.
  16023.  
  16024. Rule 4: Be aware that systems may have multiple video devices.
  16025.  
  16026. Since the Macintosh II is able to support multiple screen devices, make sure your
  16027. application takes into account the variable-sized desktop. For instance, a document
  16028. may have been dragged to an alternate screen on one system, and then copied and used
  16029. on another system. You should leave the document positioned where it is if it lies
  16030. within the desktop, but move it to the main screen if it doesn’t. Please refer to the
  16031. Graphics Devices chapter for more details.
  16032.  
  16033. Figure 3 helps to illustrate the relationships between the various parts of the color
  16034. system.
  16035.  
  16036. •••Refer to Figure 3.•••
  16037.  
  16038. Figure 3–The Macintosh II Color System
  16039.  
  16040. _______________________________________________________________________________
  16041.  
  16042. »From Color to Pixel
  16043.  
  16044. To help illustrate the interconnections of the color system, let’s examine the steps
  16045. from the specification of a color to the display of that color on the screen. This is
  16046. an oversimplified explanation that you should use for conceptual understanding only.
  16047.  
  16048. First, you specify the color that you want to display. Color QuickDraw stores the RGB
  16049. components so that it knows the exact color that you specified. Let’s assume that the
  16050. screen is set to eight bits per pixel. This means that each pixel is able to have
  16051. 2^8, or 256, different values. Associated with the screen is a structure called a
  16052. color table, which is a list of all the colors that the screen is currently able to
  16053. display. So in this case the color table has 256 RGB values in it, one for each
  16054. possible pixel value. The first entry in the color table specifies the color of all
  16055. pixels that have value 0, the second entry specifies the color of pixels that have
  16056. value 1, and so on. Thus the color’s position in the table determines the pixel value
  16057. that produces that color.
  16058.  
  16059. When you use Color QuickDraw to draw something, it retrieves the stored RGB, and asks
  16060. the Color Manager to return the pixel value that best represents that color. The
  16061. Color Manager effectively searches through the color table for the RGB that most
  16062. closely matches your color. The position in the table of the best match determines
  16063. the pixel value to be placed on the screen. Color QuickDraw then places that pixel
  16064. value on the screen.
  16065.  
  16066. But how does this pixel cause the assigned color to be displayed? Color QuickDraw has
  16067. placed this pixel into the RAM on the video card. While your Macintosh II is turned
  16068. on, the video card is continuously redisplaying every pixel that is stored in its RAM
  16069. (very, very quickly). Internal to the video card is another color table, the Color
  16070. Look-Up Table (CLUT). It is organized exactly like the first one, but is used the
  16071. other way around. The video card takes the pixel value and uses it to determine what
  16072. RGB value that pixel represents. It then uses that RGB to send off three signals
  16073. (red, green, and blue) to the video monitor, indicating exactly what color the current
  16074. pixel should be.
  16075.  
  16076. Some video cards allow you to change the set of colors displayed at a given time.
  16077. Although this is normally done transparently through the Palette Manager, it actually
  16078. happens when both the screen’s color table and the one that is internal to the video
  16079. card are changed to reflect the new set of colors.
  16080.  
  16081. A very slight variation of this is used to support the monochrome mode that you can
  16082. set from the control panel. When you set monochrome mode, the screen’s color table
  16083. doesn’t change: from the application’s point of view, the same set of colors is still
  16084. available. Instead, when the video card is told to use monochrome mode, it replaces
  16085. each entry in the video card’s internal color table with a level of gray (R=G=B) that
  16086. matches the luminance of the color it is replacing. Because of this, the switch
  16087. between color and monochrome modes has no effect on a running program.
  16088.  
  16089. _______________________________________________________________________________
  16090.  
  16091.  
  16092. æKY About…Color…QuickDraw
  16093. æC »ABOUT COLOR QUICKDRAW                                      ColorQuickDraw
  16094. _______________________________________________________________________________
  16095.  
  16096. The most fundamental difference between the original QuickDraw and Color QuickDraw is
  16097. the environment in which drawing takes place. In the original QuickDraw, all drawing
  16098. is performed in a grafPort, the structure that defines the coordinate system, drawing
  16099. pattern, background pattern, pen size and location, character font and style, and bit
  16100. map in which drawing takes place. In Color QuickDraw, drawing takes place in a color
  16101. grafPort (cGrafPort) instead. As described in later sections, most of the fields in a
  16102. cGrafPort are the same as fields in a grafPort; however, a few fields have been
  16103. changed to hold color information.
  16104.  
  16105. When you’re using a grafPort in your application, you can specify up to eight colors.
  16106. When drawing to a color screen or printing, these colors will actually be displayed.
  16107. When drawing to an offscreen bitmap, the colors will be lost
  16108. (since an offscreen bitmap only has one bit for each pixel).
  16109.  
  16110. When you’re using a cGrafPort, however, you can specify up to 2^48 colors. The number
  16111. of colors that are displayed depends on the setting of the screen, the capability of
  16112. the printer, or the depth of the offscreen pixmap. There is more information about
  16113. offscreen pixmaps in the “Drawing to Offscreen Devices” section of the next chapter.
  16114.  
  16115. Color grafPorts are used by the system in the same way as grafPorts. They are the
  16116. same size as grafPorts, and they are the structures upon which a program builds color
  16117. windows. As with a grafPort, you set thePort to be a cGrafPort using the SetPort
  16118. command.
  16119.  
  16120. You can use all old drawing commands when drawing into a cGrafPort, and you can use
  16121. all new drawing commands when drawing into a grafPort. However, since new drawing
  16122. commands that are used in a grafPort don’t take advantage of any of the features of
  16123. Color QuickDraw, it’s not recommended.
  16124.  
  16125. _______________________________________________________________________________
  16126.  
  16127. »Drawing Color in a GrafPort
  16128.  
  16129. Although the QuickDraw graphics routines were designed mainly for monochrome drawing,
  16130. they also included some rudimentary color capabilities. A pair of fields in the
  16131. grafPort record, fgColor and bkColor, allow a foreground and background color to be
  16132. specified. The color values used in these fields are based on a planar model: each
  16133. bit position corresponds to a different color plane, and the value of each bit indicates
  16134. whether a particular color plane should be activated. (The term color plane refers to
  16135. a logical plane, rather than a physical plane.) The individual color planes combine
  16136. to produce the
  16137. full-color image.
  16138.  
  16139. The standard QuickDraw color values consist of one bit for normal monochrome drawing
  16140. (black on white), one bit for inverted monochrome (white on black), three bits for
  16141. the additive primary colors (red, green, blue) used in video display, and four bits
  16142. for the subtractive primary colors (cyan, magenta, yellow, black) used in hardcopy
  16143. printing. The original QuickDraw interface includes a set of predefined constants for
  16144. the standard colors:
  16145.  
  16146. CONST
  16147.   blackColor   = 33;
  16148.   whiteColor   = 30;
  16149.   redColor     = 209;
  16150.   greenColor   = 329;
  16151.   blueColor    = 389;
  16152.   cyanColor    = 269;
  16153.   magentaColor = 149;
  16154.   yellowColor  = 89;
  16155.  
  16156. These are the only colors available in the original QuickDraw. All programs that draw
  16157. into grafPorts are limited to these eight colors. When these colors are drawn to the
  16158. screen on the Macintosh II, Color QuickDraw automatically draws them in color, if the
  16159. screen is set to a color mode.
  16160.  
  16161. _______________________________________________________________________________
  16162.  
  16163. »Drawing Color in a CGrafPort
  16164.  
  16165. Color QuickDraw represents color using the RGBColor record type, which specifies the
  16166. red, blue, and green components of the color. Three 16-bit unsigned integers give the
  16167. intensity values for the three additive primary colors:
  16168.  
  16169. TYPE
  16170.     RGBColor = RECORD
  16171.                  red:     INTEGER;    {red component}
  16172.                  green:   INTEGER;    {green component}
  16173.                  blue:    INTEGER     {blue component}
  16174.                END;
  16175.  
  16176. A color of this form is referred to as an RGB value and is the form in which an
  16177. application specifies the colors it needs. The translation from the RGB value to the
  16178. pixel value is performed at the time the color is drawn.  At times the pixel value is
  16179. stored in the fgColor or bkColor fields. Refer to the Graphics Devices chapter for
  16180. more details.
  16181.  
  16182. When drawing is actually performed, QuickDraw calls the Color Manager to supply the
  16183. color that most closely matches the requested color for the current device. As described
  16184. in the Color Manager chapter, you can replace the method used for color matching if
  16185. necessary. Normally pixel values are handled entirely by Color QuickDraw and the
  16186. Color Manager; applications only refer to colors as RGB values.
  16187.  
  16188. A set of colors is grouped into a structure called a color table:
  16189.  
  16190. TYPE
  16191.   CTabHandle = ^CTabPtr;
  16192.   CTabPtr    = ^ColorTable;
  16193.   ColorTable = RECORD
  16194.                  ctSeed:    LONGINT;     {unique identifier from table}
  16195.                  ctFlags:    INTEGER;    {contains flags describing the }
  16196.                                          { specArray; clear for a pixMap}
  16197.                  ctSize:     INTEGER;    {number of entries -1 }
  16198.                                          { in ctTable}
  16199.                  ctTable:    cSpecArray
  16200.                END;
  16201.  
  16202. The fields of a color table are fully described in the Color Manager chapter. The
  16203. ctFlags field contains flags that differentiate between a device color table and an
  16204. image color table. The ctTable field is composed of a cSpecArray, which contains an
  16205. array of ColorSpec entries. Notice that each entry in the color table is a ColorSpec,
  16206. not simply an RGBColor. The type ColorSpec is composed of a value field and an RGB
  16207. value, as shown below.
  16208.  
  16209. TYPE
  16210.   cSpecArray : ARRAY [0..0] of ColorSpec;
  16211.   ColorSpec = RECORD
  16212.                 value:    INTEGER;    {pixel value}
  16213.                 rgb:      RGBColor    {RGB value}
  16214.               END;
  16215.  
  16216. Color tables are used to represent the set of colors that a device is capable of
  16217. displaying, and they are used to describe the desired colors in an image. If the
  16218. color table describes an image’s colors, then a ColorSpec determines the desired RGB
  16219. for the pixel value stored in the value field. This is the most common usage, and
  16220. most of the routines described in this chapter work with a ColorSpec in this manner.
  16221.  
  16222. If the color table describes a device’s colors, then the value field in a ColorSpec
  16223. is reserved for use by the Color Manager. In most cases your application won’t change
  16224. the device color table. If you want to know more about the device color table, refer
  16225. to the Color Manager chapter for more details.
  16226.  
  16227. _______________________________________________________________________________
  16228.  
  16229.  
  16230. æKY The…Color…Graphics…Port
  16231. æC »THE COLOR GRAPHICS PORT                                    ColorQuickDraw
  16232. _______________________________________________________________________________
  16233.  
  16234. As described above, programs designed to take advantage of the more powerful new
  16235. color facilities available on the Macintosh II must use a new form of graphics port,
  16236. the color graphics port (type cGrafPort).  Color grafPorts will generally be created
  16237. indirectly, as a result of opening a color window with the new routines NewCWindow,
  16238. GetNewCWindow, and NewCDialog.
  16239.  
  16240. In addition, the old routines GetNewWindow, GetNewDialog, Alert, StopAlert, NoteAlert,
  16241. and CautionAlert will open a color grafPort if certain resources
  16242. (types 'wctb', 'dctb', or 'actb') are present. Refer to the chapters on the Window
  16243. and Dialog Managers for more details.
  16244.  
  16245. The new cGrafPort structure is the same size as the old-style grafPort and most of
  16246. its fields are unchanged. The old portBits field, which formerly held a complete
  16247. 14-byte BitMap record embedded within the grafPort, has been replaced by a 4-byte
  16248. PixMapHandle (portPixMap), freeing 10 bytes for other uses. (In particular, the new
  16249. portVersion field, in the position previously occupied by the bit map’s rowBytes
  16250. field, always has its two high
  16251.  
  16252. bits set; these bits are used to distinguish cGrafPorts from grafPorts, in which the
  16253. two high bits of rowBytes are always clear. See Figure 4.) Similarly, the old bkPat,
  16254. pnPat, and fillPat fields, which previously held 8-byte patterns, have been replaced
  16255. by three 4-byte handles. The resulting 12 bytes of additional space are taken up by
  16256. two 6-byte RGBColor records.
  16257.  
  16258. The structure of the color graphics port is as follows:
  16259.  
  16260.   CGrafPtr  = ^CGrafPort;
  16261.   CGrafPort = RECORD
  16262.                 device:         INTEGER;         {device ID for font }
  16263.                                                  { selection}
  16264.                 portPixMap:     PixMapHandle;    {port's pixel map}
  16265.                 portVersion:    INTEGER;         {highest 2 bits always }
  16266.                                                  { set}
  16267.                 grafVars:       Handle;          {handle to more fields}
  16268.                 chExtra:        INTEGER;         {extra characters}
  16269.                 pnLocHFrac:     INTEGER;         {pen fraction}
  16270.                 portRect:       Rect;            {port rectangle}
  16271.                 visRgn:         RgnHandle;       {visible region}
  16272.                 clipRgn:        RgnHandle;       {clipping region}
  16273.                 bkPixPat:       PixPatHandle;    {background pattern}
  16274.                 rgbFgColor:     RGBColor;        {requested foreground }
  16275.                                                  { color}
  16276.                 rgbBkColor:     RGBColor;        {requested background }
  16277.                                                  { color}
  16278.                 pnLoc:          Point;           {pen location}
  16279.                 pnSize:         Point;           {pen size}
  16280.                 pnMode:         INTEGER;         {pen transfer mode}
  16281.                 pnPixPat:       PixPatHandle;    {pen pattern}
  16282.                 fillPixPat:     PixPatHandle;    {fill pattern}
  16283.                 pnVis:          INTEGER;         {pen visibility}
  16284.                 txFont:         INTEGER;         {font number for text}
  16285.                 txFace:         Style;           {text's character style}
  16286.                 txMode:         INTEGER;         {text's transfer mode}
  16287.                 txSize:         INTEGER;         {font size for text}
  16288.                 spExtra:        Fixed;           {extra space}
  16289.                 fgColor:        LONGINT;         {actual foreground color}
  16290.                 bkColor:        LONGINT;         {actual background color}
  16291.                 colrBit:        INTEGER;         {plane being drawn}
  16292.                 patStretch:     INTEGER;         {used internally}
  16293.                 picSave:        Handle;          {picture being saved}
  16294.                 rgnSave:        Handle;          {region being saved}
  16295.                 polySave:       Handle;          {polygon being saved}
  16296.                 grafProcs:      CQDProcsPtr      {low-level drawing }
  16297.                                                  { routines}
  16298.               END;
  16299.  
  16300. Field descriptions
  16301.  
  16302. portPixMap     The portPixMap field contains a handle to the port’s pixel
  16303.                map. This is the structure that describes the cGrafPort’s pixels.
  16304.  
  16305. portVersion    The two high bits of the portVersion field are always set.
  16306.                This allows Color QuickDraw to tell the difference between a
  16307.                grafPort and a cGrafPort. The remainder of the field gives
  16308.                the version number of Color QuickDraw that created this port.
  16309.                (Initial release is version 0.)
  16310.  
  16311. grafVars       The grafVars field contains a handle to additional fields.
  16312.  
  16313. chExtra        The chExtra field is used in proportional spacing. It specifies
  16314.                a fixed point number by which to widen every character,
  16315.                excluding the space character, in a line of text. (The number
  16316.                is in 4.12 fractional notation: four bits of signed integer
  16317.                followed by 12 bits of fraction. This number is multiplied by
  16318.                txSize before it is used.) Default chExtra is 0.
  16319.  
  16320. pnLocHFrac     The pnLocHFrac field contains the fractional horizontal pen
  16321.                position used when drawing text. The initial pen fraction is 1/2.
  16322.  
  16323. bkPixPat       The bkPixPat field contains a handle to the background pixel
  16324.                pattern.
  16325.  
  16326. rgbFgColor     The rgbFgColor field contains the requested foreground color.
  16327.  
  16328. rgbBkColor     The rgbBkColor field contains the requested background color.
  16329.  
  16330. pnPixPat       The pnPixPat field contains a handle to the pixel pattern for
  16331.                pen drawing.
  16332.  
  16333. fillPixPat     The fillPixPat field contains a handle to the pixel pattern for
  16334.                area fill; for internal use only. Notice that this is not in
  16335.                the same location as old fillPat.
  16336.  
  16337. fgColor        The fgColor field contains the pixel value of the foreground
  16338.                color supplied by the Color Manager. This is the best available
  16339.                approximation to rgbFgColor.
  16340.  
  16341. bkColor        The bkColor field contains the pixel value of the background
  16342.                color supplied by the Color Manager. This is the best available
  16343.                approximation to rgbBkColor.
  16344.  
  16345. colrBit        The colrBit field is reserved: not for use by applications.
  16346.  
  16347. grafProc       The grafProc field used with a cGrafPort contains a CQDProcsPtr,
  16348.                instead of the QDProcsPtr used with a grafPort.
  16349.  
  16350. All remaining fields have the same meanings as in the old-style grafPort.
  16351.  
  16352. •••Refer to Figure 4.•••
  16353.  
  16354. Figure 4–Color QuickDraw Fields
  16355. _______________________________________________________________________________
  16356.  
  16357. »Pixel Images
  16358.  
  16359. The representation of a color image in memory is a pixel image, analogous to the bit
  16360. image used by the original QuickDraw. The number of bits per pixel is called the
  16361. depth of the image; a pixel image one bit deep is equivalent to a bit image. On the
  16362. Macintosh II, the pixel image that appears on a video screen is normally stored on a
  16363. graphics card rather than in main memory. To increase speed, your program can build
  16364. additional images in RAM for rapid transfer to the display device. This technique,
  16365. called drawing to an offscreen bitmap, is described in the Graphics Devices chapter.
  16366.  
  16367. There are several possible arrangements of a pixel image in memory. The size and
  16368. structure of a pixel image is described by the pixel map data structure; this structure
  16369. and its various forms are discussed below. See Figure 5 for a representation of a
  16370. pixel image on a system with screen depth set to eight.
  16371.  
  16372. _______________________________________________________________________________
  16373.  
  16374. »Pixel Maps
  16375.  
  16376. Just as the original QuickDraw does all of its drawing in a bit map, Color QuickDraw
  16377. uses an extended data structure called a pixel map (pixMap). In addition to the
  16378. dimensions and contents of a pixel image, the pixel map also includes information on
  16379. the image’s storage format, depth, resolution, and color usage:
  16380.  
  16381. TYPE
  16382.  PixMapHandle = ^PixMapPtr;
  16383.  PixMapPtr    = ^PixMap;
  16384.  PixMap       = RECORD
  16385.                   baseAddr:      Ptr;           {pointer to pixMap data}
  16386.                   rowBytes:      INTEGER;       {offset to next row}
  16387.                   bounds:        Rect;          {boundary rectangle}
  16388.                   pmVersion:     INTEGER;       {color QuickDraw version }
  16389.                                                 { number}
  16390.                   packType:      INTEGER;       {packing format}
  16391.                   packSize:      LONGINT;       {size of data in packed }
  16392.                                                 { state}
  16393.                   hRes:          Fixed;         {horizontal resolution}
  16394.                   vRes:          Fixed;         {vertical resolution}
  16395.                   pixelType:     INTEGER;       {format of pixel image}
  16396.                   pixelSize:     INTEGER;       {physical bits per pixel}
  16397.                   cmpCount:      INTEGER;       {logical components per }
  16398.                                                 { pixel}
  16399.                   cmpSize:       INTEGER;       {logical bits per component}
  16400.                   planeBytes:    LONGINT;       {offset to next plane}
  16401.                   pmTable:       CTabHandle;    {absolute colors for this }
  16402.                                                 { image}
  16403.                   pmReserved:    LONGINT        {reserved for future }
  16404.                                                 { expansion}
  16405.                 END;
  16406.  
  16407. Field descriptions
  16408.  
  16409. baseAddr      The baseAddr field contains a pointer to first byte of the
  16410.               pixel image, the same as in a bitMap. For optimal performance
  16411.               this should be a multiple of four.
  16412.  
  16413. rowBytes      The rowBytes field contains the offset in bytes from one row of
  16414.               the image to the next, the same as in a bitMap. As before,
  16415.               rowBytes must be even. The high three bits of rowBytes are used
  16416.               as flags. If bit 15 = 1, the data structure is a pixMap;
  16417.               otherwise it is a bitMap. Bits 14 and 13 are not used and must
  16418.               be 0.
  16419.  
  16420. bounds        The bounds field is the boundary rectangle, which defines the
  16421.               coordinate system and extent of the pixel map; it’s similar to
  16422.               a bitMap. This rectangle is in pixels, so depth has no effect
  16423.               on its values.
  16424.  
  16425. pmVersion     The pmVersion is the version number of Color QuickDraw that
  16426.               created this pixel map, which is provided for future
  16427.               compatibility. (Initial release is version 0.)
  16428.  
  16429. packType      The packType field identifies the packing algorithm used to
  16430.               compress image data. Color QuickDraw currently supports only
  16431.               packType = 0, which means no packing.
  16432.  
  16433. packSize      The packSize field contains the size of the packed image in
  16434.               bytes. When packType = 0, this field should be set to 0.
  16435.  
  16436. hRes          The hRes is the horizontal resolution of pixMap data in pixels
  16437.               per inch.
  16438.  
  16439. vRes          The vRes is the vertical resolution of pixMap data in pixels
  16440.               per inch. By default, hRes = vRes = 72 pixels per inch.
  16441.  
  16442. pixelType     The pixelType field specifies the storage format for a pixel
  16443.               image. 0 = chunky, 1 = chunky/planar, 2 = planar. Only chunky
  16444.               is used in the Macintosh II.
  16445.  
  16446. pixelSize     The pixelSize is the physical bits per pixel; it’s always a
  16447.               power of 2.
  16448.  
  16449. cmpCount      The cmpCount is the number of color components per pixel. For
  16450.               chunky pixel images, this is always 1.
  16451.  
  16452. cmpSize       The cmpSize field contains the logical bits per RGBColor
  16453.               component. Note that (cmpCount*cmpSize) doesn’t necessarily
  16454.               equal pixelSize. For chunky pixel images, cmpSize = pixelSize.
  16455.  
  16456. planeBytes    The planeBytes field is the offset in bytes from one plane to
  16457.               the next. If only one plane is used, as is the case with chunky
  16458.               pixel images, this field is set to 0.
  16459.  
  16460. pmTable       The pmTable field is a handle to table of colors used in the
  16461.               pixMap. This may be a device color table or an image color table.
  16462.  
  16463. pmReserved    The pmReserved field is reserved for future expansion; it must
  16464.               be set to 0 for future compatibility.
  16465.  
  16466. The data in a pixel image can be organized several ways, depending on the characteristics
  16467. of the device or image. The pixMap data structure supports three pixel image formats:
  16468. chunky, planar, and chunky/planar.
  16469.  
  16470. In a chunky pixel image, all of a pixel’s bits are stored consecutively in memory,
  16471. all of a row’s pixels are stored consecutively, and rowBytes indicates the offset in
  16472. memory from one row to the next. This is the only one of the three formats that’s
  16473. supported by this implementation of Color QuickDraw. The pixel depths that are currently
  16474. supported are 1, 2, 4, and 8 bits per pixel. In a chunky pixMap cmpCount = 1 and
  16475. cmpSize = pixelSize. Figure 5 shows a chunky pixel image for a system with screen
  16476. depth set to eight.
  16477.  
  16478. A planar pixel image is a pixel image separated into distinct bit images in memory,
  16479. one for each color plane. Within the bit image, rowBytes indicates the offset in
  16480. memory from one row to the next. PlaneBytes indicates the offset in memory from one
  16481. plane to the next. The planar format isn’t supported by this implementation of Color
  16482. QuickDraw.
  16483.  
  16484. A chunky/planar pixel image is separated into distinct pixel images in memory, typically
  16485. one for each color component. Within the pixel image, rowBytes indicates the offset
  16486. in memory from one row to the next. PlaneBytes indicates the offset in memory from
  16487. one plane to the next. The chunky/planar format isn’t supported by this implementation
  16488. of Color QuickDraw.
  16489.  
  16490. •••Refer to Figure 5.•••
  16491.  
  16492. Figure 5–A Pixel Image
  16493.  
  16494. _______________________________________________________________________________
  16495.  
  16496. »Pixel Patterns
  16497.  
  16498. With Color QuickDraw, monochrome patterns are replaced by a new form of pattern
  16499. structure, the pixel pattern, which offers greater flexibility in the use of color. 
  16500. The three pattern fields in a grafPort—pnPat, bkPat, and fillPat—have been replaced
  16501. by the pnPixPat, bkPixPat, and fillPixPat fields in a cGrafPort. The format for a
  16502. pixel pattern is shown below:
  16503.  
  16504. TYPE
  16505.   PixPatHandle = ^PixPatPtr;
  16506.   PixPatPtr    = ^PixPat;
  16507.   PixPat       = RECORD
  16508.                    patType:      INTEGER;         {pattern type}
  16509.                    patMap:       PixMapHandle;    {pattern characteristics}
  16510.                    patData:      Handle;          {pixel image defining }
  16511.                                                   { pattern}
  16512.                    patXData:     Handle;          {expanded pixel image}
  16513.                    patXValid:    INTEGER;         {flags for expanded }
  16514.                                                   { pattern data}
  16515.                    patXMap:      Handle;          {handle to expanded }
  16516.                                                   { pattern data}
  16517.                    pat1Data:      Pattern;        {old-style pattern/RGB }
  16518.                                                   { color}
  16519.                  END;
  16520.  
  16521. Field descriptions
  16522.  
  16523. patType      The patType field specifies the pattern’s type. The possible
  16524.              values include: 0 = old-style pattern, 1 = full-color pixel
  16525.              pattern, 2 = RGB pattern.
  16526.  
  16527. patMap       The patMap field is a handle to the pixel map describing the
  16528.              pattern’s pixel image.
  16529.  
  16530. patData      The patData field is a handle to the pattern’s pixel image.
  16531.  
  16532. patXData     The patXData field is a handle to an expanded pixel image used
  16533.              internally by Color QuickDraw.
  16534.  
  16535. patXValid    When the pattern’s data or color table change, you can
  16536.              invalidate the expanded data by setting the patXValid field to –1.
  16537.  
  16538. patXMap      The patXMap field is a handle that is reserved for use by Color
  16539.              QuickDraw.
  16540.  
  16541. pat1Data    The pat1Data field contains an old-style 8-by-8 pattern to be
  16542.             used when this pattern is drawn into old grafPort. NewPixPat
  16543.             sets this field to 50% gray.
  16544.  
  16545. Old-style patterns are still supported. When used in a cGrafPort, the QuickDraw
  16546. routines PenPat and BackPat store the pattern within pnPixPat and bkPixPat, respectively,
  16547. and set the patType to 0 to indicate that the structure contains old pattern data.
  16548. Such patterns are limited to the original 8-by-8 dimensions and are always drawn
  16549. using the values in the cGrafPort’s rgbFgColor and rgbBkColor fields. Similarly,
  16550. filled drawing operations, such as FillRect, are also supported.
  16551.  
  16552. In a pixel pattern (patType = 1), the pattern’s dimensions, depth, resolution
  16553. (only 72 pixels per inch is supported), set of colors, and other characteristics are
  16554. defined by a pixel map, referenced by the patMap handle. Since the pixel map has its
  16555. own color table, pixel patterns can consist of any number of colors, and don’t usually
  16556. use the foreground and background colors. The section on relative patterns, below,
  16557. describes an exception to this rule.
  16558.  
  16559. Furthermore, patType = 1 patterns are not limited to a fixed size: their height and
  16560. width can be any power of 2, as specified by the height and width of
  16561. patMap^^.bounds. (Notice that a pattern eight bits wide—the original QuickDraw size—has
  16562. a row width of just one byte, contrary to the usual rule that the rowBytes field must
  16563. be even.) This pattern type is generally read into memory using the GetPixPat routine,
  16564. or set using the PenPixPat or BackPixPat routines.
  16565.  
  16566. Although the patMap defines the pattern’s characteristics, its baseAddr field is
  16567. ignored; for a type1 pattern, the actual pixel image defining the pattern is stored
  16568. in the handle in the pattern’s patData field. The pattern’s depth need not match that
  16569. of the pixel map it’s painted into; the depth will be adjusted automatically when the
  16570. pattern is drawn. Color QuickDraw maintains a private copy of the pattern’s pixel
  16571. image, expanded to the current screen depth, and aligned to the current grafPort or
  16572. cGrafPort, in the patXData field.
  16573.  
  16574. The third pattern type is RGBPat (patType = 2). Using the MakeRGBPat routine, the
  16575. application can specify the exact color it wants to use. QuickDraw selects a pattern
  16576. to approximate that color. In this way, an application can effectively increase the
  16577. color resolution of the screen. Pixel patterns are particularly useful for dithering:
  16578. mixing existing colors together to create the illusion of a third color that’s unavailable
  16579. on a particular device. The MakeRGBPat routine aids in this process by constructing a
  16580. dithered pattern to approximate a given absolute color. (See the description of
  16581. MakeRGBPat in the
  16582. “Color QuickDraw Routines” section for more details.) In the current implementation
  16583. of Color QuickDraw, an RGBPat can display 125 different patterns on a 4-bit-deep
  16584. screen, or 2197 different patterns on an 8-bit-deep screen.
  16585.  
  16586. For an RGBPat, the RGB defines the image; there is no image data. An RGBPat has an
  16587. 8-by-8, 2-bit-deep pattern.
  16588.  
  16589. A program that creates a pixMap must initialize the pixMap’s color table to describe
  16590. the pixels. GetCTable could be used to read such a table from a resource file; you
  16591. could then dispose of the pixMap’s color table and replace it with the one returned
  16592. by GetCTable.
  16593.  
  16594. »Relative Patterns
  16595.  
  16596. Type1 pixel patterns contain color tables that describe the colors they use. Generally
  16597. such a color table contains one entry for each color used in the pattern. For instance,
  16598. if your pattern has five colors in it, you would probably create a four-bit-per-pixel
  16599. pattern that uses pixel values 0–4, and a color table with five entries, numbered
  16600. 0–4, that contain the RGB specifications for those pixel values.
  16601.  
  16602. When the pattern is drawn, each possible pixel value that isn’t specified in the
  16603. color table is assigned a color. The largest unassigned pixel value becomes the
  16604. foreground color; the smallest unassigned pixel value is assigned the background
  16605. color. Remaining unassigned pixel values are given colors that are evenly distributed
  16606. between the foreground and background.
  16607.  
  16608. For instance, in the color table mentioned above, pixel values 5–15 are unused.
  16609. Assume that the foreground color is black and the background color is white. Pixel
  16610. value 15 is assigned the foreground color, black; pixel value 5 is assigned the
  16611. background color, white; the nine pixel values between them are assigned evenly
  16612. distributed shades of gray. If the pixMap’s color table is set to NIL, all pixel
  16613. values are determined by blending the foreground and background colors.
  16614.  
  16615. _______________________________________________________________________________
  16616.  
  16617. »Transfer Modes
  16618.  
  16619. A transfer mode is a method of placing information on the display devices. It involves
  16620. an interaction between what your application is drawing (the source) and what’s
  16621. already there (the destination). The original QuickDraw offered eight basic transfer
  16622. modes:
  16623.  
  16624.   •  completely replacing the destination with the source (Copy), and its
  16625.      inverse (NotCopy)
  16626.   •  combining the destination with the source (Or), and its inverse (NotOr)
  16627.   •  selectively clearing the destination with the source (Bic, for “bit
  16628.      clear”), and its inverse (NotBic)
  16629.   •  selectively inverting the destination with the source (Xor), and its
  16630.      inverse (NotXor)
  16631.  
  16632. This is how color affects these eight transfer modes when the source pixels are
  16633. either black (all 1’s) or white (all 0’s):
  16634.  
  16635. Copy        The Copy mode applies the foreground color to the black part of
  16636.             the source (the part containing 1’s) and the background color to
  16637.             the white part of the source (the part containing 0’s), and
  16638.             replaces the destination with the colored source.
  16639.  
  16640. NotCopy     The NotCopy mode applies the foreground color to the white part
  16641.             of the source and the background color to the black part of the
  16642.             source, and replaces the destination with the colored source. It
  16643.             thus has the effect of reversing the foreground and background
  16644.             colors.
  16645.  
  16646. Or          The Or mode applies the foreground color to the black part of the
  16647.             source and replaces the destination with the colored source. The
  16648.             white part of the source isn’t transferred to the destination. If
  16649.             the foreground is black, the drawing will be faster.
  16650.  
  16651. NotOr       The NotOr mode applies the foreground color to the white part of
  16652.             the source and replaces the destination with the colored source.
  16653.             The black part of the source isn’t transferred to the destination.
  16654.             If the foreground is black, the drawing will be faster.
  16655.  
  16656. Bic         The Bic mode applies the background color to the black part of
  16657.             the source and replaces the destination with the colored source.
  16658.             The white part of the source isn’t transferred to the destination.
  16659.  
  16660. NotBic      The NotBic mode applies the background color to the white part
  16661.             of the source and replaces the destination with the colored source.
  16662.             The black part of the source isn’t transferred to the destination.
  16663.  
  16664. Xor         The Xor mode complements the bits in the destination corresponding
  16665.             to the bits equal to 1 in the source. When used on a colored
  16666.             destination, the color of the inverted destination isn’t defined.
  16667.  
  16668. NotXor      The NotXor mode inverts the bits that are 0 in the source. When
  16669.             used on a colored destination, the color of the inverted
  16670.             destination isn’t defined.
  16671.  
  16672. Pixels of colors other than black and white aren’t all 1’s or all 0’s, so the application
  16673. of a foreground color or a background color to the pixel produces an undefined result.
  16674. For this reason, and because a pixPat already contains color, the foreground and
  16675. background colors are ignored when your application is drawing with a pixPat. When
  16676. your program draws a pixMap the foreground and background colors are not ignored.
  16677. Make sure that the foreground is black and the background is white before you call
  16678. CopyBits or the result will be undefined.
  16679.  
  16680. If you intend to draw with pixMaps or pixPats, you will probably want to use the Copy
  16681. mode or one of the arithmetic modes described in the following section.
  16682.  
  16683. To help make color work well on different screen depths, Color QuickDraw does some
  16684. validity checking of the foreground and background colors. If your application is
  16685. drawing to a cGrafPort with a depth equal to 1 or 2, and if the RGB values of the
  16686. foreground and background colors aren’t the same, but both of them map to the same
  16687. pixel value, then the foreground color is inverted. This ensures that, for instance,
  16688. red text drawn on a green background doesn’t map to black on black.
  16689.  
  16690. _______________________________________________________________________________
  16691.  
  16692. »Arithmetic Drawing Modes
  16693.  
  16694. Color QuickDraw uses a set of arithmetic drawing modes designed specifically for use
  16695. with color. These modes change the destination pixels by performing arithmetic operations
  16696. on the source and destination pixels. These drawing modes are most useful in 8-bit
  16697. color, but work on 4-bit and 2-bit color as well. If the destination bitmap is one
  16698. bit deep, the mode reverts to one of the old transfer modes that approximates the
  16699. arithmetic mode requested.
  16700.  
  16701. Each drawing routine converts the source and destination pixels to their RGB components,
  16702. performs an operation on each pair of components to provide a new RGB value for the
  16703. destination, and then assigns the destination a pixel value close to the calculated
  16704. RGB value. The arithmetic modes listed below can be used for all drawing operations;
  16705. your application can pass them as a parameter to TextMode, PenMode, or CopyBits.
  16706.  
  16707. addOver    This mode assigns to the destination pixel the color closest to
  16708.            the sum of the source and destination RGB values. If the sum of
  16709.            any of the RGB components exceeds the maximum allowable value,
  16710.            65,535, the RGB value wraps around to the value less 65,536.
  16711.            AddOver is slightly faster than addPin. If the destination bitmap
  16712.            is one bit deep, addOver reverts to Xor.
  16713.  
  16714. addPin     This mode assigns to the destination pixel the color closest to
  16715.            the sum of the destination RGB values, pinned to a maximum allowable
  16716.            RGB value. For grafPorts, the pin value is always white. For
  16717.            cGrafPorts, the pin value is assigned using OpColor. If the
  16718.            destination bitmap is one bit deep, addPin reverts to Bic.
  16719.  
  16720. subOver    This mode assigns to the destination pixel the color closest to
  16721.            the difference of the source and destination RGB values. If the
  16722.            result is less than 0, the RGB value wraps around to 65,536 less
  16723.            the result. SubOver is slightly faster than subPin. If the
  16724.            destination bitmap is one bit deep, subOver reverts to Xor.
  16725.  
  16726. subPin     This mode assigns to the destination pixel the color closest to
  16727.            the difference of the sum and the destination RGB values, pinned
  16728.            to a minimum allowable RGB value. For grafPorts, the pin value is
  16729.            always black. In a cGrafPort, the pin value is assigned by using
  16730.            OpColor. If the destination bitmap is one bit deep, subPin reverts
  16731.            to Or.
  16732.  
  16733. adMax      (Arithmetic Drawing Max) This mode compares the source and
  16734.            destination pixels, and replaces the destination pixel with the
  16735.            color containing the greater saturation of each of the RGB
  16736.            components. Each RGB component comparison is done independently,
  16737.            so the resulting color isn’t necessarily either the source or the
  16738.            destination color. If the destination bitmap is one bit deep,
  16739.            adMax reverts to Bic.
  16740.  
  16741. adMin      (Arithmetic Drawing Min) This mode compares the source and
  16742.            destination pixels, and replaces the destination pixel with
  16743.            the color containing the lesser saturation of each of the RGB
  16744.            components. Each RGB component is compared independently, so
  16745.            the resulting color isn’t necessarily the source or the
  16746.            destination color. If the destination bitmap is one bit deep,
  16747.            adMin reverts to Or.
  16748.  
  16749. blend      This mode replaces the destination pixel with a weighted average
  16750.            of the colors of the source and destination pixels. The formula
  16751.            used to calculate the destination is:
  16752.  
  16753.              dest = source*weight/65,536 + destination*(1-weight/65,536)
  16754.  
  16755.            where weight is an unsigned value between 1 and 65,535. In a
  16756.            grafPort, the weight is set to 50% gray, so that equal weights
  16757.            of the source and destination RGB components are combined to
  16758.            produce the destination color. In a cGrafPort, the weight is an
  16759.            RGBColor that individually specifies the weights of the red,
  16760.            green, and blue components. The weight is assigned using OpColor.
  16761.            If the destination bitmap is one bit deep, blend reverts to Copy.
  16762.  
  16763. Because drawing with the arithmetic modes uses the closest matching pixel values, and
  16764. not necessarily exact matches, these modes might not produce the results you expect.
  16765. For instance, suppose srcCopy mode is used to paint a green pixel on the screen in
  16766. 4-bit mode. Of the 16 colors available, the closest green may contain a small amount
  16767. of red, as in RGB components of 300 red, 65,535 green, and 0 blue. AddOver is then
  16768. used to paint a red pixel on top of the green pixel, ideally resulting in a yellow
  16769. pixel. The red pixel’s RGB components are 65,535 red, 0 green, and 0 blue. Adding the
  16770. red components together wraps to 300, since the largest representable value is 65,535.
  16771. In this case, AddOver would cause no visible change at all. Using AddPin with an
  16772. opColor of white would produce the desired results.
  16773.  
  16774. On the Macintosh II the rules for setting the pen mode and the text mode have been
  16775. relaxed slightly. It’s no longer necessary to specify a pattern mode or a source mode
  16776. (patCopy as opposed to srcCopy) to perform a particular operation. QuickDraw will
  16777. choose the correct drawing mode automatically. However, to be compatible with earlier
  16778. versions of QuickDraw, you application must specify the correct drawing mode. Text
  16779. and bitmaps should always use a source mode; rectangles, regions, polygons, arcs,
  16780. ovals, round rectangles, and lines should always use a pattern mode.
  16781.  
  16782. The constants used for the arithmetic transfer modes are as follows:
  16783.  
  16784. CONST
  16785.  blend      = 32;
  16786.  addPin     = 33;
  16787.  addOver    = 34;
  16788.  subPin     = 35;
  16789.  adMax      = 37;
  16790.  subOver    = 38;
  16791.  adMin      = 39;
  16792.  
  16793. Warning:  Unlike the rest of QuickDraw, the arithmetic modes don’t call the
  16794.           Color Manager when mapping a requested RGB value to a pixel value.
  16795.           If your application replaces the color matching routines, you must
  16796.           either not use these modes, or you must maintain the inverse table
  16797.           using the Color Manager routines.
  16798.  
  16799. _______________________________________________________________________________
  16800.  
  16801. »Replace with Transparency
  16802.  
  16803. The transparent mode replaces the destination pixel with the source pixel if the
  16804. source pixel isn’t equal to the background color. This mode is most useful in 8-bit,
  16805. 4-bit, or 2-bit color modes. To specify a transparent pattern, use the drawing mode
  16806. transparent+patCopy. If the destination pixMap is one bit deep, the mode is translated
  16807. to Or. Transparency can be specified as a parameter to TextMode, PenMode, or CopyBits.
  16808.  
  16809. Transparent mode is optimized to handle source bitmaps with large transparent holes,
  16810. as an alternative to specifying an unusual clipping region or mask parameter to
  16811. CopyMask. Patterns aren’t optimized, and may not draw as quickly.
  16812.  
  16813. The constant used for transparent mode is
  16814.  
  16815. CONST
  16816.  transparent     = 36;
  16817.  
  16818. _______________________________________________________________________________
  16819.  
  16820. »The Hilite Mode
  16821.  
  16822. This new method of highlighting exchanges the background color and the highlight
  16823. color in the destination. This has the visual effect of using a highlighting pen to
  16824. select the object. For instance, TextEdit uses the hilite mode to select text: if the
  16825. highlight color is yellow, selected text appears on a yellow background. In general,
  16826. highlighting should be used in place of inversion when selecting and deselecting
  16827. objects such as text or graphics.
  16828.  
  16829. There are two ways to use hilite mode. The easiest is to call
  16830.  
  16831.   BitClr (Ptr(HiliteMode,pHiliteBit));
  16832.  
  16833. just before calling InvertRect, InvertRgn, InvertArc, InvertRoundRct, or InvertPoly
  16834. or any drawing using srcXor mode. On a one-bit-deep destination, this will work
  16835. exactly like inversion, and is compatible with all versions of QuickDraw. Color
  16836. QuickDraw resets the hilite bit after performing each drawing operation, so the
  16837. hilite bit should be cleared immediately before calling a routine that is to do
  16838. highlighting. Routines that formerly used Xor inversion, such as the Invert routines,
  16839. Paint, Frame, LineTo, text drawing, and CopyBits, will now use hilite mode if the
  16840. hilite bit is clear.
  16841.  
  16842. Assembly language note:  You can use
  16843.  
  16844.                            BCLR #hiliteBit, hiliteMode
  16845.  
  16846.                          Do not alter the other bits in HiliteMode.
  16847.  
  16848. The second way to use hilite mode is to pass it directly to TextMode, PenMode, or
  16849. CopyBits as a parameter.
  16850.  
  16851. Hilite mode uses the source or pattern to decide which bits to exchange; only bits
  16852. that are on in the source or pattern can be highlighted in the destination.
  16853.  
  16854. A very small inversion should probably not use hilite mode, because a small selection
  16855. in the hilite color might be too hard to see. TextEdit, for instance, uses hilite
  16856. mode to select and deselect text, but not to blink the insertion point.
  16857.  
  16858. Hilite mode is optimized to look for consecutive pixels in either the hilite or
  16859. background colors. For example, if the source is an all black pattern, the highlighting
  16860. will be especially fast, operating internally on a long word at a time instead of a
  16861. pixel at a time. Highlighting a large area without such consecutive pixels (a gray
  16862. pattern, for instance) can be slow.
  16863.  
  16864. The global variable HiliteRGB is read from parameter RAM when the machine starts. Old
  16865. grafPorts use the RGB values in the global HiliteRGB as the highlight color. Color
  16866. grafPorts default to the global HiliteRGB, but can be overridden by the HiliteColor
  16867. procedure.
  16868.  
  16869. The constants used with hilite mode are listed below:
  16870.  
  16871. CONST
  16872.   hilite      = 50;
  16873.   pHiliteBit  = 0;    {this is the correct value for use when calling }
  16874.                       { the BitClear trap. BClr must use the assembly }
  16875.                       { language equate hiliteBit}
  16876. _______________________________________________________________________________
  16877.  
  16878.  
  16879. æKY The…Color…Cursor
  16880. æC »THE COLOR CURSOR                                           ColorQuickDraw
  16881. _______________________________________________________________________________
  16882.  
  16883. Color QuickDraw supports the use of color cursors. The size of a cursor is still
  16884. 16-by-16 pixels. The new CCrsr data structure is substantially different from the
  16885. Cursor data structure used with the original QuickDraw: the CCrsr fields crsr1Data,
  16886. crsrMask, and crsrHotSpot are the only fields that have counterparts in the Cursor
  16887. record.
  16888.  
  16889. The structure of the color cursor is as follows:
  16890.  
  16891. TYPE
  16892.    CCrsrHandle = ^CCrsrPtr;
  16893.    CCrsrPtr    = ^CCrsr;
  16894.    CCrsr       = RECORD
  16895.                    crsrType:       INTEGER;          {type of cursor}
  16896.                    crsrMap:        PixMapHandle;     {the cursor's pixmap}
  16897.                    crsrData:       Handle;           {cursor's data}
  16898.                    crsrXData:      Handle;           {expanded cursor data}
  16899.                    crsrXValid:     INTEGER;          {depth of expanded data}
  16900.                    crsrXHandle:    Handle;           {Reserved for future }
  16901.                                                      { use}
  16902.                    crsr1Data:      Bits16;           {one-bit cursor}
  16903.                    crsrMask:       Bits16;           {cursor's mask}
  16904.                    crsrHotSpot:    Point;            {cursor's hotspot}
  16905.                    crsrXTable:     LONGINT;          {private}
  16906.                    crsrID:         LONGINT;          {ctSeed for expanded }
  16907.                                                      { cursor}
  16908.                  END;
  16909.  
  16910. You will not normally need to manipulate the fields of a color cursor. Your application
  16911. can load in a color cursor using the GetCCursor routine, and display it using the
  16912. SetCCursor routine. When the application is finished using a color cursor, it should
  16913. dispose of it using the DisposCCursor routine. These routines are discussed below in
  16914. the section “Color QuickDraw Routines”.
  16915.  
  16916. Color cursors are stored in resources of type 'crsr'. The format of the 'crsr' resource
  16917. is given in the section “Color QuickDraw Resource Formats”.
  16918.  
  16919. Field descriptions
  16920.  
  16921. crsrType       The crsrType field specifies the type of cursor. Possible
  16922.                values are: $8000 = old cursor, $8001 = new cursor.
  16923.  
  16924. crsrMap        The crsrMap field is a handle to the pixel map defining the
  16925.                cursor’s characteristics.
  16926.  
  16927. crsrData       The crsrData field is a handle to the cursor’s pixel data.
  16928.  
  16929. crsrXData      The crsrXData field is a handle to the expanded pixel image
  16930.                used internally by Color QuickDraw (private).
  16931.  
  16932. crsrXValid     The crsrXValid field contains the depth of the expanded cursor
  16933.                image. If you change the cursor’s data or color table, you
  16934.                should set this field to 0 to cause the cursor to be reexpanded.
  16935.                You should never set it to any other values.
  16936.  
  16937. crsrXHandle    The crsrXHandle field is reserved for future use.
  16938.  
  16939. crsr1Data      The crsr1Data field contains a 16-by-16 one-bit image to be
  16940.                displayed when the cursor is on 1-bit or 2-bit per pixel screens.
  16941.  
  16942. crsrMask       The crsrMask field contains the cursor’s mask data. The same
  16943.                1-bit-deep mask is used with crsrData and crsr1Data.
  16944.  
  16945. crsrHotSpot    The crsrHotSpot field contains the cursor’s hot spot.
  16946.  
  16947. crsrXTable     The crsrXTable field is reserved for future use.
  16948.  
  16949. crsrID         The crsrID field contains the ctSeed for the cursor.
  16950.  
  16951. The first four fields of the CCrsr record are similar to the first four fields of the
  16952. PixPat record, and are used in the same manner by Color QuickDraw. See the discussion
  16953. of the patMap field under the section titled “Pixel Patterns” for more information on
  16954. how the crsrMap is used.
  16955.  
  16956. The display of a cursor involves a relationship between a mask, stored in the crsrMask
  16957. field with the same format used for old cursor masks, and an image. There are two
  16958. possible sources for a color cursor’s image. When the cursor is on a screen whose
  16959. depth is one or two bits per pixel, the image for the cursor is taken from Crsr1Data,
  16960. which contains old-style cursor data. In this case, the relationship between data and
  16961. mask is exactly as before.  When the screen depth is greater than two bits per pixel,
  16962. the image for the cursor is taken from crsrMap and crsrData; the relationship between
  16963. mask and data is described in the following paragraph.
  16964.  
  16965. The data pixels within the mask replace the destination pixels. The data pixels
  16966. outside the mask are displayed using an XOR with the destination pixels. If data
  16967. pixels outside the mask are 0 (white), the destination pixels aren’t changed. If data
  16968. pixels outside the mask are all 1’s (black), the destination pixels are complemented.
  16969. All other values outside of the mask cause unpredictable results.
  16970.  
  16971. To work properly, a color cursor’s image should contain white pixels
  16972. (R = G = B = $FFFF) for the transparent part of the image, and black pixels
  16973. (R = G = B = $0000) for the inverting part of the image, in addition to the other
  16974. colors in the cursor’s image. Thus, to define a cursor that contains two colors, it’s
  16975. necessary to use a 2-bit-per-pixel cursor image (that is, a four-color image).
  16976.  
  16977. If your application changes the value of your cursor data or its color table, it
  16978. should set the crsrXValid field to 0 to indicate that the cursor’s data needs to be
  16979. reexpanded, and assign a new unique value to crsrID (unique values can be obtained
  16980. using the GetCTSeed routine); then it should call SetCCursor to display the changed
  16981. cursor.
  16982.  
  16983. _______________________________________________________________________________
  16984.  
  16985.  
  16986. æKY Color…Icons
  16987. æC »COLOR ICONS                                                ColorQuickDraw
  16988. _______________________________________________________________________________
  16989.  
  16990. A new data structure, known as CIcon, supports the use of color icons. The structure
  16991. of the color icon is as follows:
  16992.  
  16993. TYPE
  16994.    CIconHandle = ^CIconPtr;
  16995.    CIconPtr    = ^CIcon;
  16996.    CIcon       = RECORD
  16997.                    iconPMap:        PixMap;    {the icon's pixMap}
  16998.                    iconMask:        BitMap;    {the icon's mask bitmap}
  16999.                    iconBMap:        BitMap;    {the icon's bitMap}
  17000.                    iconData:        Handle;    {the icon's data}
  17001.                    iconMaskData:    ARRAY[0..0] OF INTEGER;
  17002.                                                {icon's mask and bitmap }
  17003.                                                { data}
  17004.                  END;
  17005.  
  17006. You won’t normally need to manipulate the fields of color icons. Your application can
  17007. load a color icon into memory using the routine GetCIcon. To draw a color icon that’s
  17008. already in memory, use PlotCIcon. When your application is through with a color icon,
  17009. it can dispose of it using the DisposCIcon routine. These routines are discussed
  17010. below in the section “Color QuickDraw Routines”.
  17011.  
  17012. Color icons are stored in a resource file as resource type 'cicn'. The format of the
  17013. 'cicn' resource is given in the section “Using Color QuickDraw
  17014. Resources”.
  17015.  
  17016. Field descriptions
  17017.  
  17018. iconPMap        The iconPMap field contains the pixel map describing the
  17019.                 icon. Note that pixMap is inline, not a handle.
  17020.  
  17021. iconMask        The iconMask field contains a bit map for the icon’s mask.
  17022.  
  17023. iconBMap        The iconBMap field contains a bit map for the icon.
  17024.  
  17025. iconData        The iconData field contains a handle to the icon’s pixel image.
  17026.  
  17027. iconMaskData    The iconMaskData field is an array containing the icon’s mask
  17028.                 data followed by the icon’s bitmap data. This is only used
  17029.                 when the icon is stored as a resource.
  17030.  
  17031. You can use color icons in menus in the same way that you could use old icons in
  17032. menus. The menu definition procedure first tries to load in a 'cicn' with the specified
  17033. resource ID. If it doesn’t find one, then it tries to load in an
  17034. 'ICON' with that ID. The Dialog Manager will also use a 'cicn' in place of an
  17035. 'ICON' if there is one with the ID specified in the item list. For more information,
  17036. see the Menu Manager and Dialog Manager chapters.
  17037.  
  17038. _______________________________________________________________________________
  17039.  
  17040.  
  17041. æKY Using…Color…QuickDraw
  17042. æC »USING COLOR QUICKDRAW                                      ColorQuickDraw
  17043. _______________________________________________________________________________
  17044.  
  17045. This section gives an overview of routines that you will typically call while using
  17046. Color QuickDraw. All routines are discussed below in the section “Color QuickDraw
  17047. Routines”.
  17048.  
  17049. Using a color graphics port is much like using an old-style grafPort. The old routines
  17050. SetPort and GetPort operate on grafPorts or cGrafPorts, and the global variable
  17051. ThePort points to either to a grafPort or a cGrafPort. Color QuickDraw examines the
  17052. two high bits of the portBits.rowBytes field (the portVersion field in a cGrafPort).
  17053. If these bits equal 0, then it is a grafPort; if they are both 1, then it is a cGrafPort.
  17054. In Pascal, use type coercion to convert between GrafPtr and cGrafPtr. For example:
  17055.  
  17056.   VAR myPort: CGrafPtr;
  17057.   SetPort (GrafPtr(myPort));
  17058.  
  17059. There’s still a graphics pen for line drawing, with a current size, location, pattern,
  17060. and transfer mode; all of the old line- and shape-drawing operations, such as Move,
  17061. LineTo, FrameRect, and PaintPoly, still work just as before. However, colors should
  17062. be set with the new routines RGBForeColor and RGBBackColor (described below) instead
  17063. of the old ForeColor and BackColor routines. If your application is using the Palette
  17064. Manager, use the routines PMForeColor and PMBackColor instead.
  17065.  
  17066. PenPat and BackPat are still supported, and will construct a pixel pattern equivalent
  17067. to the specified bit pattern. The patType field of this pattern is set to 0; thus it
  17068. will always use the port’s current foreground and background colors at the time of
  17069. drawing.
  17070.  
  17071. To read a multicolored pattern from a resource file, use the GetPixPat routine. Set
  17072. these patterns using PenPixPat and BackPixPat, or pass them as parameters to Color
  17073. QuickDraw’s color fill routines (such as FillCRect). These patterns have their own
  17074. color tables and are generally not affected by the port’s foreground and background
  17075. colors (refer to the earlier discussion of relative patterns).
  17076.  
  17077. Most routines that accept bitMaps as parameters also accept pixMaps (not PixMapHandles).
  17078. Likewise, any new routine that has a pixMap as a parameter will also accept a bitMap.
  17079. This allows one set of routines to work for all operations on images; the high bit of
  17080. the rowBytes field distinguishes whether the parameter is a bitMap or a pixMap.
  17081.  
  17082. It’s worth noting here that resources are used slightly differently by Color QuickDraw
  17083. than they were used by QuickDraw. For instance, with old QuickDraw, your application
  17084. could call GetCursor before each SetCursor; the same handle would be passed back to
  17085. the application each time. With Color QuickDraw, the color cursor is a compound
  17086. structure, more complex than a simple resource handle. Color QuickDraw reads the
  17087. requested resource, copies it, and then alters the copy before passing it to the
  17088. application. Each time your application calls GetCCursor, it gets a new copy of the
  17089. cursor. This means that your program should only call GetCCursor once, even if it
  17090. does multiple SetCCursor calls. The new resource types should be marked as purgeable
  17091. if you are concerned about memory space. This discussion holds true for color cursor,
  17092. color pattern, color icon, and color table resources. 
  17093.  
  17094. _______________________________________________________________________________
  17095.  
  17096.  
  17097. æKY Color…QuickDraw…Routines
  17098. æC »COLOR QUICKDRAW ROUTINES                                   ColorQuickDraw
  17099. _______________________________________________________________________________
  17100.  
  17101. Color QuickDraw continues to support all the original QuickDraw calls described in
  17102. the QuickDraw chapter. The following sections describe in detail the new Color QuickDraw
  17103. routines, as well as changes to existing routines.
  17104.  
  17105. _______________________________________________________________________________
  17106.  
  17107. »Operations on CGrafPorts
  17108.  
  17109. PROCEDURE OpenCPort (port: CGrafPtr);
  17110.  
  17111. The OpenCPort procedure is analogous to OpenPort, except it opens a cGrafPort instead
  17112. of a grafPort. You will rarely need to use this call, since OpenCPort is called by
  17113. NewCWindow and GetNewCWindow, as well as by the Dialog Manager when the appropriate
  17114. color resources are present.  OpenCPort allocates storage for all the structures in
  17115. the cGrafPort, and then calls InitCPort to initialize them.  The new structures
  17116. allocated are the portPixMap, the pnPixPat, the fillPixPat, the bkPixPat, and the
  17117. grafVars handle.  The GrafVars record structure is shown below:
  17118.  
  17119. TYPE
  17120. GrafVars = RECORD
  17121.              rgbOpColor:        RGBColor;    {color for addPin, subPin, and }
  17122.                                              { blend}
  17123.              rgbHiliteColor:    RGBColor;    {color for highlighting}
  17124.              pmFgColor:         Handle;      {Palette handle for foreground }
  17125.                                              { color}
  17126.              pmFgIndex:         INTEGER;     {index value for foreground}
  17127.              pmBkColor:         Handle;      {Palette handle for background }
  17128.                                              { color}
  17129.              pmBkIndex:         INTEGER;     {index value for background}
  17130.              pmFlags:           INTEGER;     {Flags for Palette Manager}
  17131.            END;
  17132.  
  17133. The rgbOpColor field is initialized as black, and the rgbHiliteColor field is initialized
  17134. as the default HiliteRGB. All the rest of the GrafVars fields are initially zero.
  17135.  
  17136. The portPixMap is not allocated a color table of its own. When InitCPort is called,
  17137. the handle to the current device’s color table is copied into the portPixMap.
  17138.  
  17139. PROCEDURE InitCPort (port: CGrafPtr);
  17140.  
  17141. The InitCPort procedure does not allocate any storage. It merely initializes all the
  17142. fields in the cGrafPort to their default values.  All old fields are initialized to
  17143. the same values as a grafPort’s fields. New fields are given the following values:
  17144.  
  17145.   portPixMap:     copied from theGDevice^^.GDPMap
  17146.   portVersion:    $C000
  17147.   grafVars:       opColor initialized to black, rgbHiliteColor
  17148.                   initialized as default HiliteRGB.  All other
  17149.                   fields are initialized as 0.
  17150.   chExtra:        0
  17151.   pnLocHFrac:     1/2
  17152.   bkPixPat:       white
  17153.   rgbFgColor:     black
  17154.   rgbBkColor:     white
  17155.   pnPixPat:       black
  17156.   fillPixPat:     black
  17157.  
  17158. The default portPixMap is set to be the same as the current device’s pixMap. This
  17159. allows you to create an offscreen port that is identical to the screen’s grafPort or
  17160. cGrafPort for drawing offscreen. If you want to use a different set of colors for
  17161. offscreen drawing, you should create a new gDevice, and set it as the current gDevice
  17162. before opening the cGrafPort. Refer to the section on offscreen bitMaps in the Graphics
  17163. Devices chapter for more details.
  17164.  
  17165. As mentioned above, InitCPort does not copy the data from the current device’s color
  17166. table to the portPixMap’s color table. It simply replaces whatever is in the pmTable
  17167. field with a copy of the handle to the current device’s color table.
  17168.  
  17169. If you try to initialize a grafPort using InitCPort, it will simply return without
  17170. doing anything.
  17171.  
  17172. PROCEDURE CloseCPort (port: CGrafPtr);
  17173.  
  17174. CloseCPort releases the memory allocated to the cGrafPort. It disposes of the visRgn,
  17175. the clipRgn, the bkPixPat, the pnPixPat, the fillPixPat, and the grafVars handle. It
  17176. also disposes of the portPixMap, but doesn’t dispose of the portPixMap’s color table
  17177. (which is really owned by the gDevice). If you have placed your own color table into
  17178. the portPixMap, either dispose of it before calling CloseCPort, or store another
  17179. reference to it for other uses.
  17180.  
  17181. _______________________________________________________________________________
  17182.  
  17183. »Setting the Foreground and Background Colors
  17184.  
  17185. PROCEDURE RGBForeColor (color : RGBColor);
  17186. PROCEDURE RGBBackColor (color : RGBColor);
  17187.  
  17188. These two calls set the foreground and background colors to the best available match
  17189. for the current device. The only drawing operations that aren’t affected by these
  17190. colors are PlotCIcon, and drawing using the new color patterns. Before you call
  17191. CopyBits with a pixMap as the source, you should set the foreground to black and the
  17192. background to white.
  17193.  
  17194. If the current port is a cGrafPort, the specified RGB is placed in the rgbFgColor or
  17195. rgbBkColor field (and the pixel value most closely matching that color is placed in
  17196. the fgColor or bkColor field). If the current port is a grafPort, fgColor or bkColor
  17197. is set to the old QuickDraw color determined by taking the high bit of each of the R,
  17198. G, and B components, and using that three-bit number to select one of the eight
  17199. QuickDraw colors. The ordering of the QuickDraw colors is shown in the GetForeColor
  17200. description.
  17201.  
  17202. PROCEDURE GetForeColor (VAR color : RGBColor);
  17203. PROCEDURE GetBackColor (VAR color : RGBColor);
  17204.  
  17205. These two calls return the RGB components of the foreground and background colors set
  17206. in the current port. The calls work for both grafPorts and cGrafPorts. If the current
  17207. port is a cGrafPort, the returned value is taken directly from the rgbFgColor or
  17208. rgbBkColor field. If the current port is a grafPort, then only eight possible RGB
  17209. values can be returned. These eight values are determined by the values in a global
  17210. variable named QDColors, which is a pointer to a color table containing the current
  17211. QuickDraw colors.
  17212.  
  17213. The colors are stored in the following order:
  17214.  
  17215.   Value  Color      Red      Green    Blue
  17216.  
  17217.     0    black      $0000    $0000    $0000
  17218.     1    yellow     $FC00    $F37D    $052F
  17219.     2    magenta    $F2D7    $0856    $84EC
  17220.     3    red        $DD6B    $08C2    $06A2
  17221.     4    cyan       $0241    $AB54    $EAFF
  17222.     5    green      $0000    $8000    $11B0
  17223.     6    blue       $0000    $0000    $D400
  17224.     7    white      $FFFF    $FFFF    $FFFF
  17225.  
  17226. This is the set of colors that Color QuickDraw uses to determine precisely what
  17227. colors should be displayed by an old grafPort that is using color. The default set of
  17228. colors has been adjusted to match the colors produced on the ImageWriter II printer.
  17229.  
  17230. _______________________________________________________________________________
  17231.  
  17232. »Color Drawing Operations
  17233.  
  17234. PROCEDURE FillCRect (r: Rect; ppat: PixPatHandle);
  17235. PROCEDURE FillCOval (r: Rect; ppat: PixPatHandle);
  17236. PROCEDURE FillCRoundRect (r: Rect; ovWd,ovHt: INTEGER; ppat: PixPatHandle);
  17237. PROCEDURE FillCArc (r: Rect; startAngle,arcAngle: INTEGER; ppat: PixPatHandle);
  17238. PROCEDURE FillCRgn (rgn: RgnHandle; ppat: PixPatHandle);
  17239. PROCEDURE FillCPoly (poly: PolyHandle; ppat: PixPatHandle);
  17240.  
  17241. These calls are analogous to their similarly named counterparts in QuickDraw. They
  17242. allow a multicolored pattern to be used for filling.
  17243.  
  17244. PROCEDURE GetCPixel (h,v: INTEGER; VAR cPix: RGBColor);
  17245.  
  17246. The GetCPixel function returns the RGB of the pixel at the specified position in the
  17247. current port.
  17248.  
  17249. PROCEDURE SetCPixel (h,v: INTEGER; cPix: RGBColor);
  17250.  
  17251. The SetCPixel function sets the pixel at the specified position to the pixel value
  17252. that most closely matches the specified RGB.
  17253.  
  17254. _______________________________________________________________________________
  17255.  
  17256. »Creating Pixel Maps
  17257.  
  17258. FUNCTION NewPixMap : PixMapHandle;
  17259.  
  17260. The NewPixMap function creates a new, initialized pixMap data structure and returns a
  17261. handle to it. All fields of the pixMap are copied from the current device’s pixMap
  17262. except the color table. A handle to the color table is allocated but not initialized.
  17263.  
  17264. PROCEDURE DisposPixMap (pm: PixMapHandle);
  17265.  
  17266. The DisposPixMap procedure releases all storage allocated by NewPixMap. It disposes
  17267. of the pixMap’s color table, and of the pixMap itself. Be careful not to dispose of a
  17268. pixMap whose color table is the same as the current device’s color table.
  17269.  
  17270. PROCEDURE CopyPixMap (srcPM,dstPM: PixMapHandle);
  17271.  
  17272. The CopyPixMap routine is used for duplicating the pixMap data structure. CopyPixMap
  17273. copies the contents of the source pixMap data structure to the destination pixMap
  17274. data structure. The contents of the color table are copied, so the destination pixMap
  17275. has its own copy of the color table. Since the baseAddr field of the pixMap is a
  17276. pointer, the pointer, but not the image itself, is copied.
  17277.  
  17278. _______________________________________________________________________________
  17279.  
  17280. »Operations on Pixel Maps
  17281.  
  17282. PROCEDURE CopyBits (srcBits,dstBits: BitMap; srcRect, dstRect: Rect;
  17283.                     mode: INTEGER; maskRgn: RgnHandle);
  17284.  
  17285. CopyBits now accepts either bitMaps or pixMaps as parameters. For convenience, just
  17286. as you could pass the current port^.portBits as a parameter to CopyBits, you can now
  17287. pass GrafPtr(cPort)^.portBits. (Recall that in a cGrafPort the high two bits of the
  17288. portVersion field are set. This field, in the same position in the port as portBits.rowBytes,
  17289. indicates to QuickDraw that it has been passed a portPixMap handle.)
  17290.  
  17291. This call transfers an image from one bitMap or pixMap to another bitMap or pixMap.
  17292. The source and destination may be of different depths, of different sizes, and they
  17293. may have different color tables. Note, however, that the destination pixMap is assumed
  17294. to use the same color table as the gDevice.
  17295. (This is because an inverse table is required for translation to the destination’s
  17296. color table.)
  17297.  
  17298. During a CopyBits call, the foreground and background colors are applied to the
  17299. image. To avoid unwanted coloring of the image, set the foreground to black and the
  17300. background to white before calling this routine.
  17301.  
  17302. PROCEDURE CopyMask (srcBits,maskBits,dstBits: BitMap;
  17303.                     srcRect,maskRect,dstRect: Rect);
  17304.  
  17305. CopyMask is a new version of the CopyBits procedure, introduced in the Macintosh
  17306. Plus. It transfers an image from the source to the destination only where the corresponding
  17307. bit of the mask equals 1. The Macintosh II version will accept either a bitMap or
  17308. pixMap as the srcBits or dstBits parameters. The maskBits parameter must be a bitMap.
  17309.  
  17310. Like the Macintosh Plus version, CopyMask doesn’t send any of its drawing commands
  17311. through grafProc routines; thus CopyMask calls are not recorded in pictures. Unlike
  17312. the Macintosh Plus version, the Macintosh II version of CopyMask is able to stretch
  17313. the source and mask to fit the dstRect. The srcRect and maskRect should be the same
  17314. size. CopyMask uses the same low-level code as CopyBits, so all the same rules regarding
  17315. depth translation and color table translation apply.
  17316.  
  17317. During a CopyMask call, the foreground and background colors are applied to the
  17318. image. To avoid unwanted coloring, set the foreground to black and the background to
  17319. white before calling this routine.
  17320.  
  17321. PROCEDURE SeedCFill  (srcBits, dstBits: BitMap; srcRect, dstRect: Rect;
  17322.                       seedH, seedV: INTEGER; matchProc: ProcPtr;
  17323.                       matchData: LONGINT);
  17324.  
  17325. The SeedCFill procedure generates a mask for use with CopyMask or CopyBits, with bits
  17326. equal to 1 only in those positions where paint can leak from the starting seed point,
  17327. like the MacPaint® bucket tool.
  17328.  
  17329. Given a rectangle within a source bitMap or pixMap (srcBits), SeedCFill returns a
  17330. mask (dstBits) that contains 1’s in place of all pixels to which paint can leak from
  17331. the specified seed position (seedH, seedV), expressed in the local coordinate system
  17332. of the source pixMap. By default, paint can leak to all adjacent pixels whose RGB
  17333. value exactly match that of the seed. To use this default, set matchProc and matchData
  17334. to zero.
  17335.  
  17336. In generating the mask, SeedCFill performs CopyBits to convert srcBits to a
  17337. one-bit mask. It installs a default searchProc into the gDevice that returns 0 if the
  17338. RGB value matches that of the seed; all other RGB values return 1’s.
  17339.  
  17340. If you want to customize SeedCFill, your application can specify a matchProc that is
  17341. used instead of the default searchProc. It should return 0’s for RGB values that you
  17342. want to be filled, and 1’s for values that shouldn’t be filled. When the matchProc is
  17343. called, the GDRefCon field of the current gDevice contains a pointer to a record
  17344. having the following structure:
  17345.  
  17346. MatchRec = RECORD
  17347.              red:          INTEGER;
  17348.              green:        INTEGER;
  17349.              blue:         INTEGER;
  17350.              matchData:    LONGINT
  17351.            END;
  17352.  
  17353. In this record the red, green, and blue fields are the RGB of the pixel at the specified
  17354. seed location. MatchData is simply whatever value you passed to SeedCFill as a parameter.
  17355. For instance, your application could pass a handle to a color table whose entries
  17356. should all be filled, and then, in the matchProc, check to see if the specified RGB
  17357. matches any of the colors in the table.
  17358.  
  17359. No automatic scaling is performed: the source and destination rectangles must be the
  17360. same size. Calls to SeedCFill are not clipped to the current port and are not stored
  17361. into QuickDraw pictures.
  17362.  
  17363. PROCEDURE CalcCMask (srcBits, dstBits: BitMap; srcRect, dstRect: Rect;
  17364.                      seedRGB: RGBColor; matchProc: ProcPtr; matchData: LONGINT);
  17365.  
  17366. This routine generates a mask (dstBits) corresponding to the area in a pixMap
  17367. (srcBits) to which paint cannot leak from outside of the srcRect. The size of srcRect
  17368. must be the same as the size of dstRect.  By default, paint can leak to all adjacent
  17369. pixels whose RGB values don’t match that of the seedRGB. To use this default, set
  17370. matchProc and matchData to 0.
  17371.  
  17372. For instance, if srcBits contains a blue rectangle on a red background, and your
  17373. application calls CalcCMask with the seedRGB equal to blue, then the returned mask
  17374. has ones in the positions corresponding to the edges and interior of the rectangle,
  17375. and zeros outside of the rectangle.
  17376.  
  17377. If you want to customize CalcCMask, your application can specify a matchProc that is
  17378. used instead of the default searchProc. It should return 1’s for RGB values that
  17379. define the edges of the mask, and 0’s for values that don’t.
  17380.  
  17381. When the matchProc is called, the GDRefCon field of the gDevice contains a pointer to
  17382. a MatchRec record (the structure shown in the SeedCFill description). The red, green,
  17383. and blue fields are the RGB of the pixel at the specifed seed location. MatchData is
  17384. simply whatever value your application passed to CalcCMask as a parameter. For instance,
  17385. your program could pass a handle to a color table whose entries should all be within
  17386. the mask, and then, in the matchProc, check to see if the specified RGB matches any
  17387. of the colors in the table.
  17388.  
  17389. No automatic scaling is performed: the source and destination rectangles must be the
  17390. same size. Calls to CalcCMask are not clipped to the current port and are not stored
  17391. into QuickDraw pictures.
  17392.  
  17393. _______________________________________________________________________________
  17394.  
  17395. »Operations on Pixel Patterns
  17396.  
  17397. FUNCTION NewPixPat: PixPatHandle;
  17398.  
  17399. The NewPixPat function creates a new pixPat data structure, and returns a handle to
  17400. it. It calls NewPixMap to allocate and initialize the pattern’s pixMap to the same
  17401. settings as theGDevice^^.GDPMap, and it sets the type of the pixPat to be a color
  17402. pattern. The pat1Data field is initialized to a 50% gray pattern. New handles for
  17403. data, expanded data, expanded map, and color table are allocated but not initialized.
  17404. Including the pixPat itself, it allocates a total of six handles.  You will generally
  17405. not need to use this routine since the GetPixPat routine can be used to read in a
  17406. pattern from a resource file.
  17407.  
  17408. The sizes of the pixMap and pixPat handles are the size of their respective data
  17409. structures (see the type declarations in the “Summary” section). The other three
  17410. handles are initially small in size. Once the pattern is drawn, the size of the
  17411. expanded data is proportional to the size of the pattern data, but adjusted to the
  17412. depth of the screen. The color table size is the size of the record structure plus
  17413. eight bytes times the number of colors in the table.
  17414. _______________________________________________________________________________
  17415.  
  17416. »Creating a PixPat
  17417.  
  17418. To create a color pattern, use NewPixPat to allocate a new PixPatHandle. Set the
  17419. rowBytes, bounds, and pixelSize of the pattern’s pixMap to the dimensions of the
  17420. desired pattern. The rowBytes should be equal to (width of bounds)*pixelSize/8; it
  17421. need not be even. The width and height of the bounds must be a power of two. Each
  17422. scanline of the pattern must be at least one byte in length—that is, (width of bounds)*pixelSize
  17423. must be at least eight. Set the other fields in the pattern’s pixMap as described in
  17424. the section on the pixMap data structure.
  17425.  
  17426. Your application can explicitly specify the color corresponding to each pixel value
  17427. with the color table. The color table for the pattern must be placed in the pmTable
  17428. in the pixPat’s pixMap. Patterns may also contain colors that are relative to the
  17429. foreground and background at the time that they are drawn. Refer to the section on
  17430. the pixPat data structure for more information on relative patterns.
  17431.  
  17432. PROCEDURE DisposPixPat (ppat: PixPatHandle);
  17433.  
  17434. The DisposPixPat procedure releases all storage allocated by NewPixPat. It disposes
  17435. of the pixPat’s data handle, expanded data handle, and pixMap handle.
  17436.  
  17437. PROCEDURE CopyPixPat (srcPP,dstPP: PixPatHandle);
  17438.  
  17439. The CopyPixPat procedure copies the contents of the source pixPat to the destination
  17440. pixPat. It entirely copies all fields in the source pixPat, including the contents of
  17441. the data handle, expanded data handle, expanded map, pixMap handle, and color table.
  17442.  
  17443. FUNCTION GetPixPat (patID: INTEGER): PixPatHandle;
  17444.  
  17445. The GetPixPat call creates a new pixPat data structure, and then uses the information
  17446. in the resource of type 'ppat' and the specified ID to initialize the pixPat. The
  17447. 'ppat' resource format is described in the section “Color QuickDraw Resource Formats”.
  17448. If the resource with the specified ID is not found, then this routine returns a NIL
  17449. handle.
  17450.  
  17451. PROCEDURE MakeRGBPat (ppat: PixPatHandle; myColor: RGBColor);
  17452.  
  17453. The MakeRGBPat procedure is a new call which generates a pixPat that approximates the
  17454. specified color when drawn.  For example, if your application is drawing to a device
  17455. that has 4 bits per pixel, you will only get 16 colors if you simply set the foreground
  17456. color and draw. If you use MakeRGBPat to select a pattern, and then draw using that
  17457. pattern, you will effectively get 125 different colors. More colors are theoretically
  17458. possible; this implementation opted for a fast pattern selection rather than the best
  17459. possible pattern selection. If the device has 8 bits per pixel, you will effectively
  17460. get 2197 colors.
  17461.  
  17462. Note that these patterns aren’t usually solid; they provide a wide selection of
  17463. colors by alternating between colors with up to four colors in a pattern. For this
  17464. reason lines that are one pixel wide may not look good using these patterns. For an
  17465. RGB pattern, the patMap^^.bounds always contains (0, 0, 8, 8), and the patMap^^.rowbytes
  17466. equals 2. Figure 6 shows how these colors are arranged.
  17467.  
  17468. When MakeRGBPat creates a color table, it only fills in the last colorSpec field: the
  17469. other colorSpec values are computed at the time the drawing actually takes place,
  17470. using the current pixel depth for the system.
  17471.  
  17472.   Value    RGB
  17473.     0      computed RGB color
  17474.     1      computed RGB color
  17475.     2      computed RGB color
  17476.     3      computed RGB color
  17477.     4      RGBColor passed to MakeRGBPat routine
  17478.  
  17479. •••Refer to Figure 6.•••
  17480.  
  17481. Figure 6–RGB Pattern
  17482.  
  17483. PROCEDURE PenPixPat (ppat: PixPatHandle);
  17484. PROCEDURE BackPixPat (ppat: PixPatHandle);
  17485.  
  17486. The PenPixPat and BackPixPat calls are analogous to PenPat and BackPat, but use
  17487. multicolor pixel patterns instead of old-style patterns.  If you try to use a pixel
  17488. pattern in a grafPort, the data in the pat1Data field is placed into pnPat, bkPat, or
  17489. fillPat.
  17490.  
  17491. When your application sets a pixel pattern, the handle you provide is actually placed
  17492. into the grafPort or cGrafPort. In this way, QuickDraw can expand the pattern once
  17493. (saving it in the patXData field) when the pattern is first set, and won’t have to
  17494. reexpand it each time you set the pattern.
  17495.  
  17496. Since your handle is actually stored in the grafPort or cGrafPort, it’s considered
  17497. bad form to dispose of a PixPatHandle that is currently set as the pnPixPat or bkPixPat.
  17498. (Just in case you forget, QuickDraw will remove all references to your pattern from
  17499. existing grafPorts or cGrafPorts when you dispose of it.)
  17500.  
  17501. Using the old calls PenPat and BackPat, you can still set old-style patterns in a
  17502. cGrafPort. If necessary, it creates a new pixPatHandle in which to store the pattern
  17503. (because, as described above, pixPatHandles are owned by the application). As in old
  17504. grafPorts, old-style patterns are drawn using the foreground and background colors at
  17505. the time of drawing, not at the time the pattern is set.
  17506.  
  17507. _______________________________________________________________________________
  17508.  
  17509. »Operations on Color Cursors
  17510.  
  17511. FUNCTION GetCCursor (crsrID: INTEGER): CCrsrHandle;
  17512.  
  17513. The GetCCursor call creates a new CCrsr data structure, then initializes it using the
  17514. information in the resource of type 'crsr' with the specified ID. The 'crsr' resource
  17515. format is described in the section “Color QuickDraw Resource Formats”. If the resource
  17516. with the specified ID isn’t found, then this routine returns a NIL handle.
  17517.  
  17518. Since GetCCursor creates a new CCrsr data structure each time it is called, your
  17519. application shouldn’t call GetCCursor before each call to SetCCursor
  17520. (unlike the way GetCursor/SetCursor were normally used).  GetCCursor doesn’t dispose
  17521. or detach the resource, so resources of type 'crsr' should typically be purgeable.
  17522.  
  17523. PROCEDURE  SetCCursor (cCrsr: CCrsrHandle);
  17524.  
  17525. The SetCCursor procedure allows your application to set a multicolor cursor.  At the
  17526. time the cursor is set, it’s expanded to the current screen depth so that it can be
  17527. drawn rapidly.
  17528.  
  17529. If your application has changed the cursor’s data or its color table, it must also
  17530. invalidate the fields crsrXValid and crsrID (described in the section on the Color
  17531. Cursor data structure), before calling SetCCursor.
  17532.  
  17533. PROCEDURE DisposCCursor(cCrsr: CCrsrHandle);
  17534.  
  17535. The DisposCCursor procedure disposes all structures allocated by GetCCursor.
  17536.  
  17537. PROCEDURE AllocCursor;
  17538.  
  17539. The AllocCursor procedure reallocates cursor memory. Under normal circumstances, you
  17540. should never need to use this call, since reallocation of cursor memory is only
  17541. necessary after the depth of one of the screens has been changed.
  17542.  
  17543. _______________________________________________________________________________
  17544.  
  17545. »Operations on Color Icons
  17546.  
  17547. FUNCTION GetCIcon(id: INTEGER): CIconHandle;
  17548.  
  17549. The GetCIcon function allocates a CIcon data structure and initializes it using the
  17550. information in the resource of type 'cicn' with the specified ID. It returns the
  17551. handle to the icon’s data structure. If the specified resource
  17552. isn’t found, a NIL handle is returned.
  17553.  
  17554. The format of the 'cicn' resource is described in the section “Color QuickDraw Resource
  17555. Formats”.
  17556.  
  17557. Since GetCIcon creates a new CIcon data structure each time it is called, your application
  17558. shouldn’t call GetCIcon before each call to PlotCIcon. GetCIcon doesn’t dispose or
  17559. detach the resource, so resources of type 'cicn' should typically be purgeable.
  17560.  
  17561. PROCEDURE DisposCIcon(theIcon: CIconHandle);
  17562.  
  17563. The DisposCIcon procedure disposes all structures allocated by GetCIcon.
  17564.  
  17565. PROCEDURE PlotCIcon(theRect: Rect; theIcon: CIconHandle);
  17566.  
  17567. The PlotCIcon procedure draws the specified icon in the specified rectangle. The
  17568. iconMask field of the CIcon determines which pixels of the iconPMap are drawn and
  17569. which are not. Only pixels with 1’s in corresponding positions in the iconMask are
  17570. drawn; all other pixels don’t affect the destination. If the screen depth is one or
  17571. two bits per pixel, the iconBMap is used as the source instead of the iconPMap (unless
  17572. the rowBytes field of iconBMap is 0, indicating that there is no iconBMap.
  17573.  
  17574. When the icon is drawn, the boundsRect of the iconPMap is used as the image’s source
  17575. rectangle. The icon and its mask are both stretched to the destination rectangle. The
  17576. icon’s pixels are remapped to the current depth and color table, if necessary. The
  17577. bounds fields of the iconPMap, iconBMap, and iconMask are expected to be equal in
  17578. size.
  17579.  
  17580. PlotCIcon is simply a structured call to CopyMask. As such, it doesn’t send any of
  17581. its drawing commands through grafProc routines; thus, PlotCIcon calls are not recorded
  17582. in pictures.
  17583.  
  17584. _______________________________________________________________________________
  17585.  
  17586. »Operations on CGrafPort Fields
  17587.  
  17588. PROCEDURE SetPortPix (pm: PixMapHandle);
  17589.  
  17590. The SetPortPix call is analogous to SetPortBits, and should be used instead of SetPortBits
  17591. for cGrafPorts. It replaces the portPixMap field of the current cGrafPort with the
  17592. specified handle. SetPortPix has no effect when used with an old grafPort. If SetPortBits
  17593. is called when the current port is a cGrafPort, it does nothing.
  17594.  
  17595. PROCEDURE OpColor (color: RGBColor);
  17596.  
  17597. If the current port is a cGrafPort, the OpColor procedure sets the red, green, and
  17598. blue values used by the AddPin, SubPin, and Blend drawing modes. This information is
  17599. actually stored in the grafVars handle in the cGrafPort, but you should never need to
  17600. reference it directly. If the current port is a grafPort, OpColor has no effect.
  17601.  
  17602. PROCEDURE HiliteColor (color:RGBColor);
  17603.  
  17604. The highlight color is used by all drawing operations that use the highlight transfer
  17605. mode. When a cGrafPort is created, its highlight color is initialized from the global
  17606. variable HiliteRGB.  The HiliteColor procedure allows you to change the highlighting
  17607. color used by the current port. This information is actually stored in the grafVars
  17608. handle in the cGrafPort, but you should never need to reference it directly. If the
  17609. current port is a grafPort, HiliteColor has no effect.
  17610.  
  17611. PROCEDURE CharExtra (extra:Fixed);
  17612.  
  17613. The CharExtra procedure sets the cGrafPort’s charExtra field, which specifies the
  17614. number of pixels by which to widen every character excluding the space character in a
  17615. line of text. The charExtra field is stored in a compressed format based on the
  17616. txSize field, so you must set txSize before calling CharExtra. The initial charExtra
  17617. setting is 0. CharExtra will accept a negative number. CharExtra has no effect on
  17618. grafPorts.
  17619.  
  17620. PROCEDURE SetStdCProcs (VAR cProcs: CQDProcs);
  17621.  
  17622. This procedure sets all the fields of the given CQDProcs record to point to the
  17623. standard low-level routines. You can then change the ones you wish to point to your
  17624. own routines. For example, if your procedure that processes picture comments is named
  17625. MyComments, you will store @MyComments in the commentProc field of the CQD Procs
  17626. record.
  17627.  
  17628. When drawing in a cGrafPort, your application must always use SetStdCProcs instead of
  17629. SetStdProcs.
  17630.  
  17631. _______________________________________________________________________________
  17632.  
  17633. »Operations on Color Tables
  17634.  
  17635. FUNCTION GetCTable (ctID: INTEGER): CTabHandle;
  17636.  
  17637. The GetCTable routine allocates a new color table data structure, and initializes it
  17638. using the information in the resource of type 'clut' having the specified ID.  If the
  17639. specified resource is not found, a NIL handle is returned.
  17640.  
  17641. If you place this handle into a pixMap, you should first dispose of the handle that
  17642. was already there.
  17643.  
  17644. The format of the 'clut' resource is given in the section “Color QuickDraw Resource
  17645. Formats”.  Resource ID values 0..127 are reserved for system use. Any
  17646. 'clut' resources defined by your application should have IDs in the range
  17647. 128..1023. This value must be in the ctSeed field in the resource, and will be placed
  17648. in the ctSeed field of the color table (for color table identification). All other
  17649. possible seed values are used to identify newly created color tables, and color
  17650. tables that have been modified.
  17651.  
  17652. If you modify a color table, you should invalidate it by changing its ctSeed field.
  17653. You can get a new unique value for ctSeed using the routine GetCTSeed, described in
  17654. the Color Manager chapter.
  17655.  
  17656. PROCEDURE DisposCTable(cTable: CTabHandle);
  17657.  
  17658. The DisposCTable procedure disposes the handle allocated for a color table.
  17659.  
  17660. _______________________________________________________________________________
  17661.  
  17662.  
  17663. æKY Color…QuickDraw…Resource…Formats
  17664. æC »COLOR QUICKDRAW RESOURCE FORMATS                           ColorQuickDraw
  17665. _______________________________________________________________________________
  17666.  
  17667. Several new resource types have been defined for use with Color QuickDraw. They
  17668. are
  17669.  
  17670.   'crsr'    Color cursor resource type
  17671.   'ppat'    Pixel Pattern resource type
  17672.   'cicn'    Color Icon resource type
  17673.   'clut'    Color Look-Up Table resource type
  17674.  
  17675. The precise formats of resources of these types are given below.
  17676.  
  17677. It is important to note that resources are used somewhat differently by Color QuickDraw.
  17678. For instance, with old QuickDraw, you could do a GetCursor for each SetCursor, and
  17679. the same handle would be passed back to the application each time. With Color QuickDraw,
  17680. the color cursor, icon, and pattern are compound structures, more complex than a
  17681. simple resource handle. Color QuickDraw reads the requested resource, copies it, and
  17682. then alters the copy before passing it to the application. Each time you call GetCCursor,
  17683. you get a new copy of the cursor. This means that you should do one GetCCursor call
  17684. for a cursor, even if you do multiple SetCCursor calls. These new resource types
  17685. should be marked as purgeable if you are concerned about memory space.
  17686.  
  17687. Here are the resource formats of the resources used by Color QuickDraw.  All offsets
  17688. are measured from the beginning of the resource’s data.
  17689.  
  17690. »'crsr' (Color Cursor)
  17691.  
  17692.     CCrsr               {data structure describing cursor}
  17693.         crsrType:       [2 bytes] = $8001
  17694.         crsrMap:        [4 bytes] = offset to pixMap structure
  17695.         crsrData:       [4 bytes] = offset to pixel data
  17696.         crsrXData:      [4 bytes] = 0
  17697.         crsrXValid:     [2 bytes] = 0
  17698.         crsrXHandle:    [4 bytes] = 0
  17699.         crsr1Data:      [32 bytes] = 1 bit image for cursor
  17700.         crsrMask:       [32 bytes] = cursor’s mask
  17701.         crsrHotSpot:    [4 bytes] = cursor’s hotSpot (v,h)
  17702.         crsrXTable:     [4 bytes] = 0
  17703.         crsrID:         [4 bytes] = 0
  17704.     PixMap              {pixMap describing cursor’s pixel image}
  17705.         baseAddr:       [4 bytes] = 0
  17706.         rowBytes:       [2 bytes] = rowBytes of image
  17707.         bounds:         [8 bytes] = boundary rectangle of image
  17708.         pmVersion:      [2 bytes] = 0
  17709.         packType:       [2 bytes] = 0
  17710.         packSize:       [4 bytes] = 0
  17711.         hRes:           [4 bytes] = $00480000
  17712.         vRes:           [4 bytes] = $00480000
  17713.         pixelType:      [2 bytes] = 0 = chunky
  17714.         pixelSize:      [2 bytes] = bits per pixel in image
  17715.         cmpCount:       [2 bytes] = 1
  17716.         cmpSize:        [2 bytes] = pixelsize
  17717.         planeBytes:     [4 bytes] = 0
  17718.         pmTable:        [4 bytes] = offset to color table data
  17719.         pmReserved:     [4 bytes] = 0
  17720.     pixel data          [see below]        data for cursor
  17721.     color table data    [see below]        data for color table
  17722.  
  17723. The crsrMap field of the CCrsr record contains an offset to the pixMap record from
  17724. the beginning of the resource data. The crsrData field of the CCrsr record contains
  17725. an offset to the pixel data from the beginning of the resource data. The pmTable
  17726. field of the pixMap record contains an offset to the color table data from the beginning
  17727. of the resource data. The size of the pixelData is calculated by subtracting the
  17728. offset to the pixel data from the offset to the color table data.  The color table
  17729. data consists of a color table record
  17730. (ctSeed, ctFlags, ctSize) followed by ctSize+1 color table entries. Each entry in the
  17731. color table connects a pixel value used in the pixel data to an actual RGB.
  17732.  
  17733. »'ppat' (Pixel Pattern)
  17734.  
  17735.     PixPat record      {data structure describing pattern}
  17736.         patType        [2 bytes] = 1 (full color pattern)
  17737.         patMap         [4 bytes] = offset to pixMap record
  17738.         patData        [4 bytes] = offset to pixel data
  17739.         patXData       [4 bytes] = 0
  17740.         patXValid      [2 bytes] = –1
  17741.         patXMap        [4 bytes] = 0
  17742.         pat1Data       [8 bytes] = 1 bit pattern data
  17743.     PixMap             { pixMap describing pattern’s pixel image }
  17744.         baseAddr       [4 bytes] = 0
  17745.         rowBytes       [2 bytes] = rowBytes of image
  17746.         bounds         [8 bytes] = boundary rectangle of image
  17747.         pmVersion      [2 bytes] = 0
  17748.         packType       [2 bytes] = 0
  17749.         packSize       [4 bytes] = 0
  17750.         hRes           [4 bytes] = $00480000
  17751.         vRes           [4 bytes] = $00480000
  17752.         pixelType      [2 bytes] = 0 = chunky
  17753.         pixelSize      [2 bytes] = bits per pixel in image
  17754.         cmpCount       [2 bytes] = 1
  17755.         cmpSize        [2 bytes] = pixelsize
  17756.         planeBytes     [4 bytes] = 0
  17757.         pmTable        [4 bytes] = offset to color table data
  17758.         pmReserved     [4 bytes] = 0
  17759.     pixel data         [see below]        data for pattern
  17760.     color table data   [see below]        data for color table
  17761.  
  17762. The patMap field of the pixPat record contains an offset to the pixMap record from
  17763. the beginning of the resource data. The patData field of the pixPat record contains
  17764. an offset to the pixel data from the beginning of the resource data. The pmTable
  17765. field of the pixMap record contains an offset to the color table data from the beginning
  17766. of the resource data. The size of the pixelData is calculated by subtracting the
  17767. offset to the pixel data from the offset to the color table data.  The color table
  17768. data consists of a color table record
  17769. (ctSeed, ctFlags, ctSize) followed by ctSize+1 color table entries. Each entry in the
  17770. color table connects a pixel value used in the pixel data to an actual RGB.
  17771.  
  17772. »'cicn' (Color Icon)
  17773.  
  17774.     IconPMap            {pixMap describing icon’s pixel image}
  17775.         baseAddr        [4 bytes] = 0
  17776.         rowBytes        [2 bytes] = rowBytes of image
  17777.         bounds          [8 bytes] = boundary rectangle of image
  17778.         pmVersion       [2 bytes] = 0
  17779.         packType        [2 bytes] = 0
  17780.         packSize        [4 bytes] = 0
  17781.         hRes            [4 bytes] = $00480000
  17782.         vRes            [4 bytes] = $00480000
  17783.         pixelType       [2 bytes] = 0 = chunky
  17784.         pixelSize       [2 bytes] = bits per pixel in image
  17785.         cmpCount        [2 bytes] = 1
  17786.         cmpSize         [2 bytes] = pixelsize
  17787.         planeBytes      [4 bytes] = 0
  17788.         pmTable         [4 bytes] = 0
  17789.         pmReserved      [4 bytes] = 0
  17790.     IconMask            {Mask used when drawing icon}
  17791.         baseAddr        [4 bytes] = 0
  17792.         rowBytes        [2 bytes] = rowBytes of image
  17793.         bounds          [8 bytes] = boundary rectangle of image
  17794.     IconBMap            {Image used when drawing to 1 bit screen}
  17795.         baseAddr        [4 bytes] = 0
  17796.         rowBytes        [2 bytes] = rowBytes of image
  17797.         bounds          [8 bytes] = boundary rectangle of image
  17798.     IconData            {placeholder for image’s handle}
  17799.                         [4 bytes] = 0
  17800.     MaskData            {the icon’s mask data }
  17801.                         [n bytes] n = IconMask.rowBytes*height
  17802.     BMapData            {the icon’s bitMap data }
  17803.                         [n bytes] n = IconBMap.rowBytes*height
  17804.     PMapCTab            {the icon’s color table }
  17805.                         [n bytes] n = 8+(ColorTable.ctSize+1)*CTEntrySize
  17806.     PMapData            {the icon’s image data }
  17807.                         [n bytes] n = IconPMap.rowBytes*height
  17808.  
  17809. In the calculations above:
  17810.  
  17811.      height = IconPMap^^.bounds.bottom–IconPMap^^.bounds.top.
  17812.  
  17813. IconPMap is the pixMap describing the data in the IconData field. IconMask is the
  17814. mask that is to be applied to the data when it is drawn. IconBMap is a bitMap to be
  17815. drawn when the destination is only one or two pixels deep. If the rowbytes field of
  17816. IconBMap is 0, then no data is loaded in for the IconBMap, and IconPMap is always
  17817. used when drawing the icon. MaskData is the mask’s data. It is immediately followed
  17818. by the bitMap’s data (which may be NIL). Next is the color table describing the
  17819. IconPMap, as shown below. The final entry in the resource is the pixMap’s data.
  17820.  
  17821. »'clut' (Color Table)
  17822.  
  17823.         ctSeed         [4 bytes] = 0
  17824.         ctFlags        [2 bytes] = $0000 if pixMap color table
  17825.                                  = $8000 if device color table
  17826.         ctSize         [2 bytes] = #entries – 1
  17827.         table data     [n bytes] n = 8*(ctSize+1)
  17828.  
  17829. The 'clut' resource format is an exact duplicate of a color table in memory.  Each
  17830. element in the table data is four integers (eight bytes): a value field followed by
  17831. red, green, and blue values.  If the color table is used to describe a pixMap, then
  17832. ctFlags should be set to 0, and the value field of each entry contains the pixel
  17833. value to be associated with the following RGB.  If the color table is used to describe
  17834. a device, then ctFlags should be set to $8000, and the value fields should be set to
  17835. 0.  In this case, the implicit values are based on each entry’s position in the
  17836. table.
  17837.  
  17838. There are several default color tables that are in the Macintosh II ROMs.  There is
  17839. one for each of the standard pixel depths.  The resource ID for each table is the
  17840. same as the depth.  For example, the default color table used when you switch your
  17841. system to 8 bits per pixel mode is stored with resource ID = 8.
  17842.  
  17843. There is one other default color table.  This color table defines the eight QuickDraw
  17844. colors, the colors displayed by programs using the old QuickDraw model.  This color
  17845. table has ID = 127.  Its values are given in the section
  17846. “Setting the Foreground and Background Colors”.
  17847.  
  17848. _______________________________________________________________________________
  17849.  
  17850.  
  17851. æKY Using…Text…with…QuickDraw
  17852. æC »USING TEXT WITH QUICKDRAW                                  ColorQuickDraw
  17853. _______________________________________________________________________________
  17854.  
  17855. This section explains those QuickDraw features which provide enhanced text handling
  17856. for the Macintosh Plus, Macintosh SE, and Macintosh II. The drawing mode recommended
  17857. for all applications is SrcOr, because it uses the least memory and will draw the
  17858. entire character in all cases. The SrcOr mode will only affect other parts of existing
  17859. characters if the characters overlap. In srcOr mode the color of the character is
  17860. determined by the foreground color, although text drawing is fastest when the foreground
  17861. color is black.
  17862.  
  17863. With QuickDraw, characters can kern to the left and to the right. QuickDraw begins
  17864. drawing a series of characters at the specified pen position plus the kernMax field
  17865. (part of the Font record), plus any kerning below the baseline caused by italicizing
  17866. the font. (The kernMax field denotes the kerning allowed by a given font; since its
  17867. value is normally negative, most fonts kern to the left. Italicizing also normally
  17868. moves the pen to the left.) QuickDraw then draws through the ending pen position,
  17869. plus any kerning above the baseline caused by italicizing the font (normally to the
  17870. right), plus any space required to handle the outlined or shadowed part of the character.
  17871.  
  17872. To draw text in any mode, including the kerned part of the leading and trailing
  17873. characters, it is best to draw the entire line of text at once. If the line must be
  17874. drawn in pieces, it is best to end each piece with a space character, so that the
  17875. succeeding piece can harmlessly kern left, and the last character drawn (a space)
  17876. will not have any right kerning clipped.
  17877.  
  17878. Macintosh Plus and Macintosh SE Note:  The Macintosh Plus and Macintosh SE
  17879.                                        versions of QuickDraw clip a leading
  17880.                                        left-kerning character, and do not take
  17881.                                        italicizing into account when
  17882.                                        positioning the pen. Also, it adds a
  17883.                                        constant of 32 to the width of the
  17884.                                        character imaging rectangle, causing
  17885.                                        large italicized fonts to have the
  17886.                                        rightmost character clipped in drawing
  17887.                                        modes other than srcOr.
  17888.  
  17889. The outline and shadow styles cause the outline and shadow of the character to be
  17890. drawn in the foreground color. The inside of the character, if drawn at all, is drawn
  17891. in the background color. The center of shadowed or outlined text is drawn in a grafPort
  17892. in scrBic mode if the text mode is srcOr, for compatibility with old applications.
  17893. This allows black text with a white outline on an arbitrary background. If the text
  17894. mode is srcBic, the center of shadowed or outlined text is drawn in srcOr.
  17895.  
  17896. The style underline draws the underline through the entire text line, from the pen
  17897. starting position through the ending position, plus any offsets from font or italic
  17898. kerning, as described above. If the underline is outlined or shadowed, the ends
  17899. aren’t capped, that is, consecutively drawn pieces of text should maintain a continuous
  17900. underline.
  17901.  
  17902. Macintosh Plus and Macintosh SE Note:  QuickDraw clips the right edge of the
  17903.                                        underline to the ending pen position,
  17904.                                        causing outlined or shadowed underlines
  17905.                                        to match imperfectly when text is drawn
  17906.                                        in sections.
  17907.  
  17908. One of the reasons that SrcOr is recommended is that the maximum stack space required
  17909. for a text font drawing operation can be considerable. Text drawing uses a minimum
  17910. amount of stack if the mode is srcOr, the forecolor is black, the visRgn and clipRgn
  17911. are rectangular (or at least the destination of the text is contained within a rectangular
  17912. portion of the visRgn), the text is not scaled, and the text does not have to be
  17913. italicized, boldfaced, outlined, or shadowed by QuickDraw. Otherwise, the amount of
  17914. stack required to draw all of the text at once depends most on the size and width of
  17915. the the text and the depth of the destination.
  17916.  
  17917. If QuickDraw can’t get enough stack space to draw an entire string at once, it will
  17918. draw the string in pieces. This can produce disconcerting results in modes other than
  17919. srcOr or srcBic if some of the characters overlap because of kerning or italicizing.
  17920. If the mode is srcCopy, overlapping characters will be clipped by the last drawn
  17921. character. If the mode is srcXor, pixels where the characters overlap are not drawn
  17922. at all. If the mode is one of the arithmetic modes, the arithmetic rules are followed,
  17923. ignoring that the destination may include part of the string being drawn.
  17924.  
  17925. The stack space required for a drawing operation on the Macintosh II is roughly given
  17926. by this calculation:
  17927.  
  17928.     (text width) * (text height) * (font depth) / (8 bits per byte ) + 3K
  17929.  
  17930. Font depth normally equals the screen depth.  If the amount of stack space available
  17931. is small (less than 3.5K), QuickDraw instead uses a font depth of 1, which is slow,
  17932. but uses less stack space.
  17933.  
  17934. On the Macintosh Plus, the required stack space is roughly equal to
  17935.  
  17936.     (text width) * (text height) / (8 bits per byte ) + 2K
  17937.  
  17938. _______________________________________________________________________________
  17939.  
  17940. »Text Mask Mode
  17941.  
  17942. For the Macintosh II, the maskConstant may be added to another drawing mode to cause
  17943. just the character portion of the text to be applied in the current transfer mode to
  17944. the destination. If the text font contains more than one color, or if the drawing
  17945. mode is an arithmetic mode or hilite mode, the mask mode causes only the portion of
  17946. the characters not equal to the background to be drawn.
  17947.  
  17948. The arithmetic drawing modes and hilite mode apply the character’s background to the
  17949. destination; this can lead to undesirable results if the text is drawn in pieces. The
  17950. leftmost part of a text piece is drawn on top of a previous text piece if the font
  17951. kerns to the left. The maskMode supplied in addition to these modes causes only the
  17952. foreground part of the character to be drawn. The only reasonable way to kern to the
  17953. right in text mask mode is to use srcOr, or to add trailing characters. This is
  17954. because the rightmost kern is clipped.
  17955.  
  17956. The constant used with maskMode is
  17957.  
  17958. CONST
  17959.   mask  = 64;
  17960.  
  17961. _______________________________________________________________________________
  17962.  
  17963. »Drawing with Multibit Fonts
  17964.  
  17965. Multibit fonts may have a specific color. The transfer modes may not produce the
  17966. desired results with a multibit font. The arithmetic modes, transparent mode, and
  17967. hilite mode work equally well with single bit and multibit fonts.
  17968.  
  17969. Unlike single bit fonts, multibit fonts draw quickly in srcOr only if the foreground
  17970. is white. Single bit fonts draw quickly in srcOr only if the foreground is black.
  17971. Grayscale fonts produce a spectrum of colors, rather than just the foreground and
  17972. background colors.
  17973.  
  17974. _______________________________________________________________________________
  17975.  
  17976. »Fractional Character Positioning
  17977.  
  17978. CGrafPorts maintain the fractional horizontal pen position, so that a series of text
  17979. drawing calls will accumulate the fractional position. The horizontal pen fraction is
  17980. initially set to 1/2. InitPort, Move, MoveTo, Line and LineTo reset the pen position
  17981. to 1/2. For an old grafPort, the pen fraction is hard-coded to 1/2.
  17982.  
  17983. _______________________________________________________________________________
  17984.  
  17985.  
  17986. æKY Color…Picture…Format
  17987. æC »COLOR PICTURE FORMAT                                       ColorQuickDraw
  17988. _______________________________________________________________________________
  17989.  
  17990. With the introduction of the Macintosh II, the QuickDraw picture structure has been
  17991. extended to include new color graphics opcodes. The new version 2 pictures and opcodes
  17992. solve many of the major problems encountered by developers in using PICT files, and
  17993. enable future expandibility. For example, it is now possible to specify the resolution
  17994. of bitMap data. Color can also be specified, but only chunky pixels (contiguously
  17995. stored pixel components) are currently recognized by Color QuickDraw. Your application
  17996. only needs to generate or recognize the chunky pixel format. This format is indicated
  17997. by an image or pixMap with a cmpCount = 1.
  17998.  
  17999. Most existing applications can use version 2 pictures without modification. On a
  18000. Macintosh II, version 2 pictures will draw in color (if drawn directly to the screen).
  18001.  Currently, they will print using the old QuickDraw colors. Eventually, new print
  18002. drivers will be able to take advantage of the new color information.
  18003.  
  18004. On a Macintosh 512K enhanced, Macintosh Plus, and Macintosh SE, a patch in the System
  18005. file beginning with version 4.1 provides QuickDraw with the capability to convert and
  18006. display version 2 pictures. The original Macintosh and Macintosh 512 can’t display
  18007. version 2 pictures.
  18008.  
  18009. Applications that generate pictures in the QuickDraw picture format are free to use
  18010. any or all available features to support their particular needs. Some will use only
  18011. the imaging features. You may wish to include comments in the picture that are pertinent
  18012. to the needs of your application.  In general, put a minimal  amount of information
  18013. in your PICT files and avoid redundancy. It’s reasonable for receiving applications
  18014. to ignore picture opcodes that aren’t needed.
  18015.  
  18016. _______________________________________________________________________________
  18017.  
  18018. »Differences Between Version 1 and Version 2 Pictures
  18019.  
  18020. The major differences between version 1 and version 2 pictures are listed below.
  18021.  
  18022.   •  Version 1 opcodes are a single byte; version 2 opcodes are 2 bytes in
  18023.      length. This means that old opcodes in a version 2 picture take up two
  18024.      bytes, not one.
  18025.   •  Version 1 data may start on byte boundaries; version 2 opcodes and data
  18026.      are always word-aligned.
  18027.   •  In version 2, the high bit of the rowBytes field is used to indicate a
  18028.      pixMap instead of a bitMap; pixData then replaces bitData.
  18029.   •  All unused version 2 opcodes, as well as the number of data bytes
  18030.      associated with each, have been defined. This was done so that picture
  18031.      parsing code can safely ignore unknown opcodes, enabling future use
  18032.      of these opcodes in a backward-compatible manner.
  18033.  
  18034. _______________________________________________________________________________
  18035.  
  18036. »Drawing With Version 2 Pictures in Old GrafPorts
  18037.  
  18038. Enhancements to the DrawPicture routine allow pictures created with Color QuickDraw
  18039. to be used in either a cGrafPort or an old-style grafPort. You can create a picture
  18040. using the new drawing commands in a cGrafPort, cut it, and then paste it into an
  18041. application that draws into an old grafPort. The picture will lose some of its detail
  18042. when transferred in this way, but should be sufficient for most purposes. The following
  18043. considerations apply to the use of this technique:
  18044.  
  18045.   •  The rgbFgColor and rbgBkColor fields are mapped to the old-style
  18046.      Quickdraw constant (one of eight) that most closely approximates that
  18047.      color. For a grafPort with depth greater than one, even old applications
  18048.      will be able to draw color pictures.
  18049.   •  Patterns created using MakeRGBPat are drawn as old-style patterns having
  18050.      approximately the same luminance as the original pattern.
  18051.   •  Other new patterns are replaced by the old-style pattern contained
  18052.      in the pat1Data field of the PixPat data structure. This field is
  18053.      initialized to 50% gray by the NewPixPat routine, and is initialized
  18054.      from the resource in a GetPixPat call.
  18055.   •  PixMaps in the picture are drawn without interpretation. The CopyBits
  18056.      call performs all necessary mapping to the destination screen. If
  18057.      the picture is drawn on a Macintosh Plus or a Macintosh SE, or if the
  18058.      BitsProc routine has been replaced by the application, the pixMap is
  18059.      converted to a bitMap before it’s drawn.
  18060.   •  Changes to the ChExtra and pnLocHFrac fields, and the Hilite color
  18061.      and OpColor, are ignored.
  18062.  
  18063. A new standard opcodeProc, SetStdCProc, is called by QuickDraw when it is playing
  18064. back a color picture and it sees a new opcode that it doesn’t recognize. The default
  18065. routine simply reads and ignores all undefined opcodes.
  18066.  
  18067. _______________________________________________________________________________
  18068.  
  18069. »Picture Representation
  18070.  
  18071. The PICT file is a data fork file with a 512-byte header, followed by a picture (see
  18072. Figure 7). This data fork file contains a QuickDraw (and now, Color QuickDraw) data
  18073. structure within which a graphic application, using standard QuickDraw calls, places
  18074. drawing opcodes to represent an object or image graphic data.  In the QuickDraw
  18075. picture format, pictures consist of opcodes followed by picture data.
  18076.  
  18077. •••Refer to Figure 7.•••
  18078.  
  18079. Figure 7–PICT file format.
  18080.  
  18081. _______________________________________________________________________________
  18082.  
  18083. »Picture Parsing
  18084.  
  18085. The first 512 bytes of a PICT data file contain application-specific header information.
  18086. Each QuickDraw (and Color QuickDraw) picture definition consists of a fixed-size
  18087. header containing information about the size, scaling, and version of the picture,
  18088. followed by the opcodes and picture data defining the objects drawn between the
  18089. OpenPicture and ClosePicture calls.
  18090.  
  18091. When the OpenPicture routine is called and the port is an old grafPort, a version 1
  18092. picture is opened. When the OpenPicture routine is called and the port is a cGrafPort,
  18093. then a version 2 picture is opened. If any fields in the grafPort are different than
  18094. the default entries, those fields that are different get recorded in the picture.
  18095.  
  18096. Version 4.1 of the Macintosh System file incorporates a patch to QuickDraw that will
  18097. enable QuickDraw (on machines with 128K or larger ROMs) to parse a version 2 PICT
  18098. file, read it completely, attempt to convert all Color QuickDraw color opcodes to a
  18099. suitable black-and-white representation, and draw the picture in an old grafPort. If
  18100. you are trying to display a version 2 picture on a Macintosh without the system
  18101. patch, QuickDraw won’t be able to draw the picture.
  18102.  
  18103. _______________________________________________________________________________
  18104.  
  18105. »Picture Record Structure
  18106.  
  18107. The Pascal record structure of version 1 and version 2 pictures is exactly the same.
  18108. In both, the picture begins with a picSize, then a picFrame (rect), followed by the
  18109. picture definition data. Since a picture may include any sequence of drawing commands,
  18110. its data structure is a variable-length entity. It consists of two fixed-length
  18111. fields followed by a variable-length field:
  18112.  
  18113. TYPE Picture = RECORD
  18114.                  picSize:     INTEGER;     {low order 16 bits of picture }
  18115.                                            { size}
  18116.                  picFrame:    Rect;        {picture frame, used as }
  18117.                                            { reference for scaling when }
  18118.                                            { the picture is drawn }
  18119.                  {picture definition data}
  18120.                END;
  18121.  
  18122. To maintain compatibility with the original picture format, the picSize field has not
  18123. been changed in version 2 pictures. However, the information in this field is only
  18124. useful if your application supports version 1 pictures not exceeding 32K bytes in
  18125. size. Because pictures can be much larger than the 32K limit imposed by the 2-byte
  18126. picSize field, use the GetHandleSize call to determine picture size if the picture is
  18127. in memory or the file size returned in pBFGetInfo if the picture resides in a file.
  18128.  
  18129. The picFrame field is the picture frame that surrounds the picture and gives a frame
  18130. of reference for scaling when the picture is played back. The rest of the structure
  18131. contains a compact representation of the image defined by the opcodes. The picture
  18132. definition data consists of a sequence of the opcodes listed in Table 3 in the Pict
  18133. Opcodes section, each followed by zero or more bytes of data. Every opcode has an
  18134. implicit or explicit size associated with it that indicates the number of data bytes
  18135. following that opcode, ranging from 2 to
  18136. 2^32 bytes (this maximum number of bytes applies to version 2 pictures only).
  18137.  
  18138. _______________________________________________________________________________
  18139.  
  18140. »Picture Spooling
  18141.  
  18142. In the past, images rarely exceeded the 32K practical limit placed on resources. 
  18143. Today, with the advent of scanners and other image input products, images may easily
  18144. exceed this size.  This increase in image size necessitates a means for handling
  18145. pictures that are too large to reside entirely in memory.  One solution is to place
  18146. the picture in the data fork of a PICT file, and spool it in as needed.  To read the
  18147. file, an application can simply replace the QuickDraw default getPicProc routine with
  18148. a procedure (getPICTData) that reads the picture data from a disk file; the disk
  18149. access would be transparent.  Note that this technique applies equally to version 1
  18150. (byte-opcode) and version 2
  18151. (word-opcode) pictures.
  18152.  
  18153. »Spooling a Picture From Disk
  18154.  
  18155. In order to display pictures of arbitrary size, an application must be able to import
  18156. a QuickDraw picture from a file of type PICT.  (This is the file type produced by a
  18157. Save As command from MacDraw® with the PICT option selected.)   What follows is a
  18158. small program fragment that demonstrates how to spool in a picture from the data fork
  18159. of a PICT file.  The picture can be larger than the historical 32K resource size
  18160. limitation.
  18161.  
  18162. { The following variable and procedure must be at the }
  18163. { main level of the program }
  18164.     VAR
  18165.         globalRef: INTEGER;
  18166.  
  18167.     PROCEDURE GetPICTData(dataPtr: Ptr; byteCount: INTEGER);
  18168.     {replacement for getPicProc routine}
  18169.  
  18170.         VAR
  18171.             err : INTEGER;
  18172.             longCount: LONGINT;
  18173.  
  18174.         BEGIN
  18175.             longCount := byteCount;
  18176.             {longCount is a Pascal VAR parameter and must be a LONGINT}
  18177.             err := FSRead(globalRef,longCount,dataPtr);
  18178.             {ignore errors here since it is unclear how to handle them}
  18179.         END;
  18180.  
  18181.     PROCEDURE GetandDrawPICTFile;
  18182.     {procedure to draw in a picture from a PICT file selected by the user}
  18183.  
  18184.         VAR
  18185.             wher: Point; {where to display dialog}
  18186.             reply: SFReply; {reply record}
  18187.             myFileTypes: SFTypeList; {more of the Standard File goodies}
  18188.             NumFileTypes: INTEGER;
  18189.             err: OSErr;
  18190.             myProcs: QDProcs; {use CQDProcs for a CGrafPort (a color }
  18191.                               { window)}
  18192.             PICTHand: PicHandle; {we need a picture handle for DrawPicture}
  18193.             longCount: LONGINT;
  18194.             myPB: ParamBlockRec;
  18195.  
  18196.         BEGIN
  18197.             wher.h := 20;
  18198.             wher.v := 20;
  18199.             NumFileTypes := 1; {Display PICT files}
  18200.             myFileTypes[0] := 'PICT';
  18201.             SFGetFile(wher,'',NIL,NumFileTypes,myFileTypes,NIL,reply);
  18202.             IF reply.good THEN BEGIN
  18203.                 err := FSOpen(reply.fname,reply.vrefnum,globalRef);
  18204.  
  18205.                 SetStdProcs(myProcs); {use SetStdCProcs for a CGrafPort}
  18206.                 myWindow^.grafProcs := @myProcs;
  18207.                 myProcs.getPicProc := @GetPICTData;
  18208.  
  18209.                 PICTHand := PicHandle(NewHandle(SizeOf(Picture)));
  18210.                 {get one the size of (size word + frame rectangle)}
  18211.  
  18212.                 {skip (so to speak) the MacDraw header block}
  18213.                 err := SetFPos(globalRef,fsFromStart,512);
  18214.                 longCount := SizeOf(Picture);
  18215.                 {read in the (obsolete) size word and the picture frame}
  18216.                 err := FSRead(globalRef,longCount,Ptr(PICTHand^));
  18217.  
  18218.                 DrawPicture(PICTHand,PICTHand^^.picFrame);
  18219.                 {inside of DrawPicture, QD makes repeated calls to }
  18220.                 { getPicProc to get actual picture opcodes and data. Since }
  18221.                 { we have intercepted GetPicProc, QD will call myProcs to }
  18222.                 { get getPicProc, instead of calling the default procedure}
  18223.                
  18224.                 err := FSClose(globalRef);
  18225.  
  18226.                 myWindow^.grafProcs := NIL;
  18227.                 DisposHandle(Handle(PICTHand));
  18228.  
  18229.             END; {IF reply.good}
  18230.         END;
  18231.  
  18232. »Spooling a Picture to a File
  18233.  
  18234. Spooling a picture out to a file is equally straightforward. By replacing the standard
  18235. putPicProc with your own procedure, you can create a PICT file and spool the picture
  18236. data out to the file.
  18237.  
  18238. Here is a sample of code to use as a guide:
  18239.  
  18240. {these variables and PutPICTData must be at the main program level}
  18241. VAR  PICTcount: LONGINT; {the current size of the picture}
  18242.      globalRef: INTEGER; {the file system reference number}
  18243.      newPICThand: PicHandle;
  18244.   {this is the replacement for the StdPutPic routine}
  18245. PROCEDURE PutPICTData(dataPtr: Ptr; byteCount: INTEGER);
  18246.   VAR  longCount: LONGINT;
  18247.        err: INTEGER;
  18248.   BEGIN {unfortunately, we don't know what to do with errors}
  18249.     longCount := byteCount;
  18250.     PICTCount := PICTCount + byteCount;
  18251.     err := FSWrite(globalRef, longCount, dataPtr); {ignore error…}
  18252.     IF newPICTHand <> NIL THEN newPICTHand^^.picSize := PICTCount;
  18253.    {update so QD can track the size for oddness and pad out to full words}
  18254.   END;
  18255. {Note that this assumes the picture is entirely in memory which wouldn't }
  18256. { always be the case. You could (in effect) be feeding the StdGetPic }
  18257. { procedure at the same time, or simply spooling while drawing.}
  18258. PROCEDURE SpoolOutPICTFile(PICTHand: PicHandle {the picture to spool});
  18259.   VAR  err: OSErr;
  18260.        i: INTEGER;
  18261.        wher: Point; { where to display dialog }
  18262.        longCount, Zero: LONGINT;
  18263.        pframe: Rect;
  18264.        reply: SFReply; { reply record }
  18265.        myProcs: QDProcs; {use CQDProcs for a CGrafPort (a color window)}
  18266.   BEGIN
  18267.     wher.h := 20;
  18268.     wher.v := 20;
  18269.     {get a file to output to}
  18270.     SFPutFile(wher, 'Save the PICT as:', 'untitled', NIL, reply);
  18271.     IF reply.good THEN
  18272.       BEGIN
  18273.         err := Create(reply.fname, reply.vrefnum, '????', 'PICT');
  18274.         IF (err = noerr) | (err = dupfnerr) THEN
  18275.           BEGIN
  18276.             {now open the target file and prepare to spool to it}
  18277.             signal(FSOpen(reply.fname, reply.vrefnum, globalRef));
  18278.             SetStdProcs(myProcs); {use SetStdCProcs for a CGrafPort}
  18279.             myWindow^.grafProcs := @myProcs;
  18280.             myProcs.putPicProc := @putPICTdata;
  18281.             Zero := 0;
  18282.             longCount := 2;
  18283.             PICTCount := SizeOf(Picture);
  18284.      {now write out the 512 byte header and zero (initially) the}
  18285.      { Picture structure}
  18286.             FOR i := 1 TO (512 + SizeOf(Picture)) DIV longCount DO
  18287.               Signal(FSWrite(globalRef, longCount, @Zero));
  18288.     {open a new picture and draw the old one to it; this will convert}
  18289.     { the old picture to fit the type of GrafPort to which we are}
  18290.     { currently set}
  18291.             pFrame := PICThand^^.picFrame;
  18292.             newPICTHand := NIL;
  18293.             newPICTHand := OpenPicture(pFrame);
  18294.             DrawPicture(PICTHand, pFrame); {draw the picture so the
  18295.      bottleneck will be used. In real life you could be spooling while
  18296.      doing drawing commands (you might not use DrawPicture)}
  18297.             ClosePicture;
  18298.             Signal(SetFPos(globalRef, fsFromStart, 512));
  18299.     {skip the MacDraw header}
  18300.             longCount := SizeOf(Picture);
  18301.     {write out the correct (low word of the) size and the frame at}
  18302.     { the beginning}
  18303.             Signal(FSWrite(globalRef, longCount, Ptr(newPICTHand^)));
  18304.             Signal(FSClose(globalRef));
  18305.             myWindow^.grafProcs := NIL;
  18306.             KillPicture(newPICTHand);
  18307.           END
  18308.         ELSE
  18309.           Signal(err);
  18310.       END; {IF reply.good}
  18311.   END; {OutPICT}
  18312.  
  18313. »Drawing to an Offscreen Pixel Map
  18314.  
  18315. With the advent of high resolution output devices such as laser printers, it has
  18316. become necessary to support bitmap images at resolutions higher than those supported
  18317. by the screen. To speed up the interactive manipulation of high-resolution pixel map
  18318. images, developers may want to first draw them into an off screen pixel map at screen
  18319. resolution and retain this screen version as long as the document is open.
  18320.  
  18321. Note:  You can use the formula shown in the section “Sample PICT file” to
  18322.        calculate the resolution of the source data. How to draw into an
  18323.        offscreen pixmap is described in Macintosh Technical Note #120,
  18324.        “Drawing Into an Off-Screen Pixel Map”; the Graphics Devices chapter
  18325.        also contains a section describing how to draw to an offscreen device.
  18326.  
  18327. _______________________________________________________________________________
  18328.  
  18329. »New GrafProcs Record
  18330.  
  18331. The entire opcode space has been defined or reserved, as shown in the PICT Opcodes
  18332. section in Table 3, and a new set of routines has been added to the grafProcs record.
  18333. These changes provide support for anticipated future enhancements in a way that won’t
  18334. cause old applications to crash. It works like this: when Color QuickDraw encounters
  18335. an unused opcode, it calls the new opcodeProc routine to parse the opcode data.  By
  18336. default, this routine simply ignores the data, since no new opcodes are defined
  18337. (other than HeaderOp, which is also ignored).
  18338.  
  18339. Color QuickDraw has replaced the QDProcs record with a CQDProcs record.  In a new
  18340. grafPort, you should never use the SetStdProcs routine.  If you do, it will return
  18341. the old QDProcs record, which won’t contain an entry for the stdOpcodeProc.  If you
  18342. don’t use the new SetStdCProcs routine, the first color picture that you try to
  18343. display may crash your system.
  18344. The CQDProcs record structure is shown below. Only the last seven fields are new; the
  18345. rest of the fields are the same as those in the QDProcs record.
  18346.  
  18347.    CQDProcsPtr = ^CQDProcs
  18348.    CQDProcs    = RECORD
  18349.                    textProc:       Ptr;
  18350.                    lineProc:       Ptr;
  18351.                    rectProc:       Ptr;
  18352.                    rRectProc:      Ptr;
  18353.                    ovalProc:       Ptr;
  18354.                    arcProc:        Ptr;
  18355.                    polyProc:       Ptr;
  18356.                    rgnProc:        Ptr;
  18357.                    bitsProc:       Ptr;
  18358.                    commentProc:    Ptr;
  18359.                    txMeasProc:     Ptr;
  18360.                    getPicProc:     Ptr;
  18361.                    putPicProc:     Ptr;
  18362.                    opcodeProc:     Ptr;    {fields added to QDProcs}
  18363.                    newProc1:       Ptr;    {reserved for future use}
  18364.                    newProc2:       Ptr;    {reserved for future use}
  18365.                    newProc3:       Ptr;    {reserved for future use}
  18366.                    newProc4:       Ptr;    {reserved for future use}
  18367.                    newProc5:       Ptr;    {reserved for future use}
  18368.                    newProc6:       Ptr;    {reserved for future use}
  18369.                  END;
  18370.  
  18371. _______________________________________________________________________________
  18372.  
  18373. »Picture Compatibility
  18374.  
  18375. Many applications already support PICT resources larger than 32K. The 128K ROMs (and
  18376. later) allow pictures as large as memory (or spooling) will accommodate. This was
  18377. made possible by having QuickDraw ignore the size word and simply read the picture
  18378. until the end-of-picture opcode is reached.
  18379.  
  18380. Note:  For maximum safety and convenience, let QuickDraw generate and
  18381.        interpret your pictures.
  18382.  
  18383. While the PICT data formats described in this section allow you to read or write
  18384. picture data directly, it’s best to let DrawPicture or OpenPicture and ClosePicture
  18385. process the opcodes.
  18386.  
  18387. One reason to read a picture directly by scanning the opcodes is to disassemble it;
  18388. for example, extracting a Color QuickDraw pixel map to store in a private data structure.
  18389. This shouldn’t normally be necessary, unless your application is running on a CPU
  18390. other than the Macintosh. You wouldn’t need to do it, of course, if you were using
  18391. Color QuickDraw.
  18392.  
  18393. If your application does use the picture data, be sure it checks the version information.
  18394. You may want to include an alert box in your application, indicating to users whether
  18395. a picture was created using a later version of the picture format than is currently
  18396. recognized by your application, and letting them know that some elements of the
  18397. picture can’t be displayed. If the version information indicates a QuickDraw picture
  18398. version later than the one recognized by your application, your program should skip
  18399. over the new opcodes and only attempt to parse the opcodes it knows.
  18400.  
  18401. As with reading picture data directly, it’s best to use QuickDraw to create data in
  18402. the PICT format. If you need to create PICT format data directly, it’s essential that
  18403. you understand and follow the format presented in Table 3 and thoroughly test the
  18404. data produced on both color and black and white Macintosh machines.
  18405.  
  18406. _______________________________________________________________________________
  18407.  
  18408. »Picture Format
  18409.  
  18410. This section describes the internal structure of the QuickDraw picture, consisting of
  18411. a fixed-length header (which is different for version 1 and version 2 pictures),
  18412. followed by variable-sized picture data. Your picture structure must follow the order
  18413. shown in the examples below.
  18414.  
  18415. The two fixed-length fields, picSize and picFrame, are the same for version 1 and
  18416. version 2 pictures.
  18417.  
  18418.   picSize:   INTEGER; {low-order 16 bits of picture size}
  18419.   picFrame:  RECT;    {picture frame, used as scaling reference}
  18420.  
  18421. Following these fields is a variable amount of opcode-driven data. Opcodes represent
  18422. drawing commands and parameters that affect those drawing commands in the picture.
  18423. The first opcode in any picture must be the version opcode, followed by the version
  18424. number of the picture.
  18425.  
  18426. »Picture Definition: Version 1
  18427.  
  18428. In a version 1 picture, the version opcode is $11, which is followed by version
  18429. number $01.  When parsing a version 1 picture, Color QuickDraw (or a patched QuickDraw)
  18430. assumes it’s reading an old picture, fetching a byte at a time as opcodes. An end-of-picture
  18431. byte ($FF) after the last opcode or data byte in the file signals the end of the data
  18432. stream.
  18433.  
  18434. Picture Header (fixed size of 2 bytes):
  18435.  
  18436.         $11        BYTE       {version opcode}
  18437.         $01        BYTE       {version number of picture}
  18438.  
  18439. Picture Definition Data  (variable sized):
  18440.  
  18441.         opcode BYTE       {one drawing command}
  18442.         data . . .
  18443.         opcode BYTE       {one drawing command}
  18444.         data . . .
  18445.  
  18446.         $FF               {end-of-picture opcode}
  18447.  
  18448. »Picture Definition: Version 2
  18449.  
  18450. In a version 2 picture, the first opcode is a two-byte version opcode ($0011). This
  18451. is followed by a two-byte version number ($02FF). On machines without the 4.1 System
  18452. file, the first $00 byte is skipped, then the $11 is interpreted as a version opcode.
  18453. On a Macintosh II (or a Macintosh with System file 4.1 or later), this field identifies
  18454. the picture as a version 2 picture, and all subsequent opcodes are read as words
  18455. (which are word-aligned within the
  18456. picture). On a Macintosh without the 4.1 System patch, the $02 is read as the version
  18457. number, then the $FF is read and interpreted as the end-of-picture opcode. For this
  18458. reason, DrawPicture terminates without drawing anything.
  18459.  
  18460. Picture Header (fixed size of 30 bytes):
  18461.  
  18462.         $0011        WORD       {version opcode}
  18463.         $02FF        WORD       {version number of new picture}
  18464.  
  18465.         $0C00        WORD       {reserved header opcode}
  18466.         24 bytes of data        {reserved for future Apple use}
  18467.  
  18468. Picture Definition Data (variable sized):
  18469.  
  18470.         opcode WORD       {one drawing command}
  18471.         data . . .
  18472.         opcode WORD       {one drawing command}
  18473.         data . . .
  18474.        
  18475.         $00FF WORD        {end-of-picture opcode}
  18476.  
  18477. For future expandibility, the second opcode in every version 2 picture must be a
  18478. reserved header opcode, followed by 24 bytes of data that aren’t used by your application.
  18479.  
  18480. »PicComments
  18481.  
  18482. If your application requires capability beyond that provided by the picture opcodes,
  18483. the picComment opcode allows data or commands to be passed directly to the output
  18484. device. PicComments enable MacDraw, for example, to reconstruct graphics primitives
  18485. not found in QuickDraw (such as rotated text) that are received either from the
  18486. Clipboard or from another application. PicComments are also used as a means of communicating
  18487. more effectively with the LaserWriter and with other applications via the scrap or
  18488. the PICT data file.
  18489.  
  18490. Because some operations (like splines and rotated text) can be implemented more
  18491. efficiently by the LaserWriter, some of the picture comments are designed to be
  18492. issued along with QuickDraw commands that simulate the commented commands on the
  18493. Macintosh screen. If the printer you are using has not implemented the comment commands,
  18494. it ignores them and simulates the operations using the accompanying QuickDraw commands.
  18495. Otherwise, it uses the comments to implement the desired effect and ignores the
  18496. appropriate QuickDraw-simulated commands.
  18497.  
  18498. If you are going to produce or modify your own picture, the structure and use of
  18499. these comments must be precise. The comments and the embedded QuickDraw commands must
  18500. come in the correct sequence in order to work properly.
  18501.  
  18502. Note:  Apple is currently investigating a method to register picComments.
  18503.        If you intend to use new picComments in your application, you must
  18504.        contact Apple’s Developer Technical Support to avoid conflict with
  18505.        picComment numbers used by other developers.
  18506.  
  18507. »Sample PICT File
  18508.  
  18509. An example of a version 2 picture data file that can display a single image is shown
  18510. in Table 1. Applications that generate picture data should set the resolution of the
  18511. image source data in the hRes and vRes fields of the PICT file. It’s recommended,
  18512. however, that you calculate the image resolution anyway, using the values for srcRect
  18513. and dstRect according to the following formulas:
  18514.  
  18515. horizontal resolution (hRes)  =    width of srcRect x 72
  18516.                                    ________________
  18517.                                    width of dstRect
  18518.  
  18519. vertical resolution (vRes)    =    height of srcRect x 72
  18520.                                    _________________
  18521.                                    height of dstRect
  18522.  
  18523. Table 1–PICT file example
  18524. _______________________________________________________________________________
  18525.            Size    Name          Description
  18526.          (in bytes)
  18527.              2     picSize       low word of picture size
  18528.              8     picFrame      rectangular bounding box of picture,
  18529.                                  at 72 dpi
  18530. Picture Definition Data:
  18531.  
  18532.              2     version op    version opcode = $0011
  18533.              2     version       version number = $02FF
  18534.              2     Header op     header opcode = $0C00
  18535.              4     size          total size of picture in bytes
  18536.                                  (–1 for version 2 pictures)
  18537.              16    fBBox         fixed-point bounding box
  18538.                                  (–1 for version 2 pictures)
  18539.              4     reserved      reserved for future Apple use
  18540.                                  (–1 for version 2 pictures)
  18541.              2     opbitsRect    bitMap opcode = $0090
  18542.              2     rowBytes      integer, must have high bit set to
  18543.                                  signal pixMap
  18544.              8     bounds        rectangle, bounding rectangle at
  18545.                                  source resolution
  18546.              2     pmVersion     integer, pixMap version number
  18547.              2     packType      integer, defines packing format
  18548.              4     packSize      LongInt, length of pixel data
  18549.              4     hRes          fixed, horizontal resolution (dpi) of
  18550.                                  source data
  18551.              4     vRes          fixed, vertical resolution (dpi) of
  18552.                                  source data
  18553.              2     pixelType     integer, defines pixel type
  18554.              2     pixelSize     integer, number of bits in pixel
  18555.              2     cmpCount      integer, number of components in pixel
  18556.              2     cmpSize       integer, number of bits per component
  18557.              4     planeBytes    LongInt, offset to next plane
  18558.                    pmTable       color table = 0
  18559.                    pmReserved    reserved = 0
  18560.              4     ctSeed        LongInt, color table seed
  18561.              2     ctFlags       integer, flags for color table
  18562.              2     ctSize        integer, number of entries in ctTable –1
  18563. (ctSize+1) * 8     ctTable       color lookup table data
  18564.              8     srcRect       rectangle, source rectangle at source
  18565.                                  resolution
  18566.              8     dstRect       rectangle, destination rectangle at 72 dpi
  18567.                                  resolution
  18568.              2     mode          integer, transfer mode
  18569.       see Table 5  pixData       pixel data   
  18570.              2     endPICT op    end-of-picture opcode = $00FF
  18571. _______________________________________________________________________________
  18572.  
  18573. »Color Picture Routines
  18574.  
  18575. FUNCTION OpenPicture (picFrame: Rect) : PicHandle;
  18576.  
  18577. The OpenPicture routine has been modified to take advantage of QuickDraw’s new color
  18578. capabilities. If the current port is a cGrafPort, then OpenPicture automatically
  18579. opens a version 2 picture, as described in the previous section. As before, you close
  18580. the picture using ClosePicture and draw the picture using DrawPicture.
  18581.  
  18582. _______________________________________________________________________________
  18583.  
  18584.  
  18585. æKY PICT…Opcodes
  18586. æC »PICT OPCODES                                               ColorQuickDraw
  18587. _______________________________________________________________________________
  18588.  
  18589. The opcode information in Table 3 is provided for the purpose of debugging application-generated
  18590. PICT files. Your application should generate and read PICT files only by using standard
  18591. QuickDraw or Color QuickDraw routines
  18592. (OpenPicture, ClosePicture).
  18593.  
  18594. The data types listed in Table 2 are used in the Table 3 opcode definitions. Data
  18595. formats are described in Volume I.
  18596.  
  18597. Table 2–Data types
  18598. _______________________________________________________________________________
  18599.   Type                  Size
  18600.  
  18601.   v1 opcode             1 byte
  18602.   v2 opcode             2 bytes
  18603.   integer               2 bytes
  18604.   long integer          4 bytes
  18605.   mode                  2 bytes
  18606.   point                 4 bytes
  18607.   0..255                1 byte
  18608.   –128..127             1 byte (signed)
  18609.   rect                  8 bytes (top, left, bottom, right: integer)
  18610.   poly                  10+ bytes
  18611.   region                10+ bytes
  18612.   fixed-point number    4 bytes
  18613.   pattern               8 bytes
  18614.   rowbytes              2 bytes (always an even quantity)
  18615. _______________________________________________________________________________
  18616.  
  18617. Valid picture opcodes are listed in Table 3.  New opcodes or those altered for version
  18618. 2 picture files are indicated by a leading asterisk (*). The unused opcodes found
  18619. throughout the table are reserved for Apple use. The length of the data that follows
  18620. these opcodes is pre-defined, so if they are encountered in pictures, they can simply
  18621. be skipped. By default, Color QuickDraw reads and then ignores these opcodes.
  18622.  
  18623. Table 3–PICT opcodes
  18624. _______________________________________________________________________________
  18625.   Opcode   Name                       Description                  Data Size
  18626.                                                                    (in bytes)
  18627.   $0000    NOP                        nop                          0
  18628.   $0001    Clip                       clip                         region size
  18629.   $0002    BkPat                      background pattern           8
  18630.   $0003    TxFont                     text font (word)             2
  18631.   $0004    TxFace                     text face (byte)             1
  18632.   $0005    TxMode                     text mode (word)             2
  18633.   $0006    SpExtra                    space extra (fixed point)    4
  18634.   $0007    PnSize                     pen size (point)             4
  18635.   $0008    PnMode                     pen mode (word)              2
  18636.   $0009    PnPat                      pen pattern                  8
  18637.   $000A    FillPat                    fill pattern                 8
  18638.   $000B    OvSize                     oval size (point)            4
  18639.   $000C    Origin                     dh, dv (word)                4
  18640.   $000D    TxSize                     text size (word)             2
  18641.   $000E    FgColor                    foreground color (long)      4
  18642.   $000F    BkColor                    background color (long)      4
  18643.   $0010    TxRatio                    numer (point), denom (point) 8
  18644.   $0011    Version                    version (byte)               1
  18645.   $0012    *BkPixPat                  color background pattern     variable:
  18646.                                                                    see Table 4
  18647.   $0013    *PnPixPat                  color pen pattern            variable:
  18648.                                                                    see Table 4
  18649.   $0014    *FillPixPat                color fill pattern           variable:
  18650.                                                                    see Table 4
  18651.   $0015    *PnLocHFrac                fractional pen position      2
  18652.   $0016    *ChExtra                   extra for each character     2
  18653.   $0017    *reserved for Apple use    opcode                       0
  18654.   $0018    *reserved for Apple use    opcode                       0
  18655.   $0019    *reserved for Apple use    opcode                       0
  18656.   $001A    *RGBFgCol                  RGB foreColor                variable:
  18657.                                                                    see Table 4
  18658.   $001B    *RGBBkCol                  RGB backColor                variable:
  18659.                                                                    see Table 4
  18660.   $001C    *HiliteMode                hilite mode flag             0
  18661.   $001D    *HiliteColor               RGB hilite color             variable:
  18662.                                                                    see Table 4
  18663.   $001E    *DefHilite                 Use default hilite color     0
  18664.   $001F    *OpColor                   RGB OpColor for              variable:
  18665.                                       arithmetic modes             see Table 4
  18666.   $0020    Line                       pnLoc (point), newPt (point) 8
  18667.   $0021    LineFrom                   newPt (point)                4
  18668.   $0022    ShortLine                  pnLoc (point, dh, dv         6
  18669.                                       (-128..127)   
  18670.   $0023    ShortLineFrom              dh, dv (-128..127)           2
  18671.   $0024    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18672.                                       length + data                length
  18673.   $0025    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18674.                                       length + data                length
  18675.   $0026    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18676.                                       length + data                length
  18677.   $0027    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18678.                                       length + data                length
  18679.   $0028    LongText                   txLoc (point), count         5 + text
  18680.                                       (0..255), text
  18681.   $0029    DHText                     dh (0..255), count           2 + text
  18682.                                       (0..255), text
  18683.   $002A    DVText                     dv (0..255), count           2 + text
  18684.                                       (0..255), text
  18685.   $002B    DHDVText                   dh, dv (0..255), count       3 + text
  18686.                                       (0..255), text
  18687.   $002C    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18688.                                       length + data                length
  18689.   $002D    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18690.                                       length + data                length
  18691.   $002E    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18692.                                       length + data                length
  18693.   $002F    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18694.                                       length + data                length
  18695.   $0030    frameRect                  rect                         8
  18696.   $0031    paintRect                  rect                         8
  18697.   $0032    eraseRect                  rect                         8
  18698.   $0033    invertRect                 rect                         8
  18699.   $0034    fillRect                   rect                         8
  18700.   $0035    *reserved for Apple use    opcode + 8 bytes data        8
  18701.   $0036    *reserved for Apple use    opcode + 8 bytes data        8
  18702.   $0037    *reserved for Apple use    opcode + 8 bytes data        8
  18703.   $0038    frameSameRect              rect                         0
  18704.   $0039    paintSameRect              rect                         0
  18705.   $003A    eraseSameRect              rect                         0
  18706.   $003B    invertSameRect             rect                         0
  18707.   $003C    fillSameRect               rectangle                    0
  18708.   $003D    *reserved for Apple use    opcode                       0
  18709.   $003E    *reserved for Apple use    opcode                       0
  18710.   $003F    *reserved for Apple use    opcode                       0
  18711.   $0040    frameRRect                 rect (see Note # 5 )         8
  18712.   $0041    paintRRect                 rect (see Note # 5 )         8
  18713.   $0042    eraseRRect                 rect (see Note # 5 )         8
  18714.   $0043    invertRRect                rect (see Note # 5 )         8
  18715.   $0044    fillRRect                  rect (see Note # 5 )         8
  18716.   $0045    *reserved for Apple use    opcode + 8 bytes data        8
  18717.   $0046    *reserved for Apple use    opcode + 8 bytes data        8
  18718.   $0047    *reserved for Apple use    opcode + 8 bytes data        8
  18719.   $0048    frameSameRRect             rect                         0
  18720.   $0049    paintSameRRect             rect                         0
  18721.   $004A    eraseSameRRect             rect                         0
  18722.   $004B    invertSameRRect            rect                         0
  18723.   $004C    fillSameRRect              rect                         0
  18724.   $004D    *reserved for Apple use    opcode                       0
  18725.   $004E    *reserved for Apple use    opcode                       0
  18726.   $004F    *reserved for Apple use    opcode                       0
  18727.   $0050    frameOval                  rect                         8
  18728.   $0051    paintOval                  rect                         8
  18729.   $0052    eraseOval                  rect                         8
  18730.   $0053    invertOval                 rect                         8
  18731.   $0054    fillOval                   rect                         8
  18732.   $0055    *reserved for Apple use    opcode + 8 bytes data        8
  18733.   $0056    *reserved for Apple use    opcode + 8 bytes data        8
  18734.   $0057    *reserved for Apple use    opcode + 8 bytes data        8
  18735.   $0058    frameSameOval              rect                         0
  18736.   $0059    paintSameOval              rect                         0
  18737.   $005A    eraseSameOval              rect                         0
  18738.   $005B    invertSameOval             rect                         0
  18739.   $005C    fillSameOval               rect                         0
  18740.   $005D    *reserved for Apple use    opcode                       0
  18741.   $005E    *reserved for Apple use    opcode                       0
  18742.   $005F    *reserved for Apple use    opcode                       0
  18743.   $0060    frameArc                   rect, startAngle, arcAngle   12
  18744.   $0061    paintArc                   rect, startAngle, arcAngle   12
  18745.   $0062    eraseArc                   rect, startAngle, arcAngle   12
  18746.   $0063    invertArc                  rect, startAngle, arcAngle   12
  18747.   $0064    fillArc                    rect, startAngle, arcAngle   12
  18748.   $0065    *reserved for Apple use    opcode + 12 bytes            12
  18749.   $0066    *reserved for Apple use    opcode + 12 bytes            12
  18750.   $0067    *reserved for Apple use    opcode + 12 bytes            12
  18751.   $0068    frameSameArc               rect                         4
  18752.   $0069    paintSameArc               rect                         4
  18753.   $006A    eraseSameArc               rect                         4
  18754.   $006B    invertSameArc              rect                         4
  18755.   $006C    fillSameArc                rect                         4
  18756.   $006D    *reserved for Apple use    opcode + 4 bytes             4
  18757.   $006E    *reserved for Apple use    opcode + 4 bytes             4
  18758.   $006F    *reserved for Apple use    opcode + 4 bytes             4
  18759.                                                                    size
  18760.   $0070    framePoly                  poly                         polygon
  18761.                                                                    size
  18762.   $0071    paintPoly                  poly                         polygon
  18763.                                                                    size
  18764.   $0072    erasePoly                  poly                         polygon
  18765.                                                                    size
  18766.   $0073    invertPoly                 poly                         polygon
  18767.                                                                    size
  18768.   $0074    fillPoly                   poly                         polygon
  18769.                                                                    size
  18770.   $0075    *reserved for Apple use    opcode + poly
  18771.   $0076    *reserved for Apple use    opcode + poly
  18772.   $0077    *reserved for Apple use    opcode word + poly
  18773.   $0078    frameSamePoly              (not yet implemented:        0
  18774.                                        same as 70, etc)
  18775.   $0079    paintSamePoly              (not yet implemented)        0
  18776.   $007A    eraseSamePoly              (not yet implemented)        0
  18777.   $007B    invertSamePoly             (not yet implemented)        0
  18778.   $007C    fillSamePoly               (not yet implemented)        0
  18779.   $007D    *reserved for Apple use    opcode                       0
  18780.   $007E    *reserved for Apple use    opcode                       0
  18781.   $007F    *reserved for Apple use    opcode                       0
  18782.   $0080    frameRgn                   rgn                          region size
  18783.   $0081    paintRgn                   rgn                          region size
  18784.   $0082    eraseRgn                   rgn                          region size
  18785.   $0083    invertRgn                  rgn                          region size
  18786.   $0084    fillRgn                    rgn                          region size
  18787.   $0085    *reserved for Apple use    opcode + rgn                 region size
  18788.   $0086    *reserved for Apple use    opcode + rgn                 region size
  18789.   $0087    *reserved for Apple use    opcode + rgn                 region size
  18790.   $0088    frameSameRgn               (not yet implemented:        0
  18791.                                        same as 80, etc.)
  18792.   $0089    paintSameRgn               (not yet implemented)        0
  18793.   $008A    eraseSameRgn               (not yet implemented)        0
  18794.   $008B    invertSameRgn              (not yet implemented)        0
  18795.   $008C    fillSameRgn                (not yet implemented)        0
  18796.   $008D    *reserved for Apple use    opcode                       0
  18797.   $008E    *reserved for Apple use    opcode                       0
  18798.   $008F    *reserved for Apple use    opcode                       0
  18799.   $0090    *BitsRect                  copybits, rect clipped       variable:
  18800.                                                                    see Table 4
  18801.   $0091    *BitsRgn                   copybits, rgn clipped        variable:
  18802.                                                                    see Table 4
  18803.   $0092    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18804.                                       length + data                length
  18805.   $0093    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18806.                                       length + data                length
  18807.   $0094    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18808.                                       length + data                length
  18809.   $0095    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18810.                                       length + data                length
  18811.   $0096    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18812.                                       length + data                length
  18813.   $0097    *reserved for Apple use    opcode word + 2 bytes        2+ data
  18814.                                       data length + data           length
  18815.   $0098    *PackBitsRect              packed copybits, rect        variable:
  18816.                                       clipped                      see Table 4
  18817.   $0099    *PackBitsRgn               packed copybits, rgn         variable:
  18818.                                       clipped                      see Table 4
  18819.   $009A    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18820.                                       length + data                length
  18821.   $009B    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18822.                                       length + data                length
  18823.   $009C    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18824.                                       length + data                length
  18825.   $009D    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18826.                                       length + data                length
  18827.   $009E    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18828.                                       length + data                length
  18829.   $009F    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18830.                                       length + data                length
  18831.   $00A0    ShortComment               kind (word)                  2
  18832.   $00A1    LongComment                kind (word), size            4+data
  18833.                                       (word), data
  18834.   $00A2    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18835.                                       length + data                length
  18836.   :        :                          :
  18837.   :        :                          :
  18838.   $00AF    *reserved for Apple use    opcode + 2 bytes data        2+ data
  18839.                                       length + data                length
  18840.   $00B0    *reserved for Apple use    opcode                       0
  18841.   :        :                          :
  18842.   :        :                          :
  18843.   $00CF    *reserved for Apple use    opcode                       0
  18844.   $00D0    *reserved for Apple use    opcode + 4 bytes data        4+ data
  18845.                                       length + data                length
  18846.   :        :                          :
  18847.   :        :                          :
  18848.   $00FE    *reserved for Apple use    opcode + 4 bytes data        4+ data
  18849.                                       length + data                length
  18850.   $00FF    opEndPic                   end of picture               2
  18851.   $0100    *reserved for Apple use    opcode + 2 bytes data        2
  18852.   :        :                          :
  18853.   :        :                          :
  18854.   $01FF    *reserved for Apple use    opcode + 2 bytes data        2
  18855.   $0200    *reserved for Apple use    opcode + 4 bytes data        4
  18856.   :        :                          :
  18857.   $0BFF    *reserved for Apple use    opcode + 4 bytes data        22
  18858.   $0C00    HeaderOp                   opcode                       24
  18859.   $0C01    *reserved for Apple use    opcode + 4 bytes data        24
  18860.   :        :                          :
  18861.   $7F00    *reserved for Apple use    opcode + 254 bytes data      254
  18862.   :        :                          :
  18863.   $7FFF    *reserved for Apple use    opcode + 254 bytes data      254
  18864.   $8000    *reserved for Apple use    opcode                       0
  18865.   :        :                          :
  18866.   $80FF    *reserved for Apple use    opcode                       0
  18867.   $8100    *reserved for Apple use    opcode + 4 bytes data        4+ data
  18868.                                       length + data                length
  18869.   :        :                          :
  18870.   $FFFF    *reserved for Apple use    opcode + 4 bytes data        4+ data
  18871.                                       length + data                length
  18872. _______________________________________________________________________________
  18873.  
  18874. Notes to Table 3
  18875.  
  18876.   1.  The opcode value has been extended to a word for version 2 pictures.
  18877.       Remember, opcode size = 1 byte for version 1.
  18878.   2.  Because opcodes must be word aligned in version 2 pictures, a byte
  18879.       of 0 (zero) data is added after odd-size data.
  18880.   3.  The size of reserved opcodes has been defined. They can occur only
  18881.       in version 2 pictures.
  18882.   4.  All unused opcodes are reserved for future Apple use and should
  18883.       not be used.
  18884.   5.  For opcodes $0040–$0044: rounded-corner rectangles use the setting
  18885.       of the ovSize point (refer to opcode $000B)
  18886.   6.  For opcodes $0090 and $0091: data is unpacked. These opcodes can
  18887.       only be used for rowbytes less than 8.
  18888.   7.  For opcodes $0100–$7FFF: the amount of data for opcode
  18889.       $nnXX = 2 * nn bytes.
  18890.  
  18891. _______________________________________________________________________________
  18892.  
  18893. »The New Opcodes: Expanded Format
  18894.  
  18895. The expanded format of the version 2 PICT opcodes is shown in Table 4 below.
  18896.  
  18897. Table 4–Data Format of Version 2 PICT Opcodes
  18898. _______________________________________________________________________________
  18899.   Opcode   Name             Description                Reference to Notes
  18900.  
  18901.   $0012    BkPixPat         color background pattern   See Note 1
  18902.   $0013    PnPixPat         color pen pattern          See Note 1
  18903.   $0014    FillPixPat       color fill pattern         See Note 1
  18904.   $0015    PnLocHFrac       fractional pen             If pnLocHFrac <> 1/2, it
  18905.                              position (word)            is always put to the
  18906.                                                         picture before each
  18907.                                                         text drawing operation.
  18908.  
  18909.   $0016    ChExtra          extra for each             After chExtra changes,
  18910.                              character (word)           it is put to picture
  18911.                                                         before next text
  18912.                                                         drawing operation.
  18913.   $001A    RGBFgCol        RGB foreColor (RBGColor)    desired RGB for
  18914.                                                         foreground
  18915.   $001B    RGBBkCol        RGB backColor (RGBColor)    desired RGB for
  18916.                                                         background
  18917.   $001D    HiliteColor     RGB hilite color
  18918.   $001F    OpColor         RGB OpColor for
  18919.                             arithmetic modes
  18920.   $001C    HiliteMode      hilite mode flag            No data; this opcode is
  18921.                                                         sent before a drawing
  18922.                                                         operation that uses the
  18923.                                                         hilite mode.
  18924.   $001E    DefHilite       Use default hilite          No data; set hilite
  18925.                             color                       to default (from low
  18926.                                                         memory).
  18927.   $0090    BitsRect        copybits, rect              See Note 2,4,5
  18928.                             clipped
  18929.   $0091    BitsRgn         copybits, rgn               See Note 3,4,5
  18930.                             clipped
  18931.   $0098    PackBitsRect    packed copybits,            See Note 2,4
  18932.                             rect clipped
  18933.   $0099    PackBitsRgn     packed copybits,            See Note 3,4
  18934.                             rgn clipped
  18935. _______________________________________________________________________________
  18936.  
  18937. Notes to Table 4
  18938.  
  18939.   1.  if patType = ditherPat 
  18940.       then
  18941.           PatType:   word;        {pattern type = 2}
  18942.           Pat1Data:  Pattern;     {old pattern data}
  18943.           RGB:       RGBColor;    {desired RGB for pattern}
  18944.       else
  18945.           PatType:   word;        {pattern type = 1}
  18946.           Pat1Data:  Pattern;     {old pattern data}
  18947.           pixMap:                 {described in Table 5}
  18948.           colorTable:             {described in Table 5}
  18949.  
  18950.           pixData:                {described in Table 5}
  18951.       end;
  18952.  
  18953.   2.  pixMap:                     {described in Table 5}
  18954.       colorTable:                 {described in Table 5}
  18955.       srcRect:       Rect;        {source rectangle} 
  18956.       dstRect:       Rect;        {destination rectangle} 
  18957.       mode:          Word;        {transfer mode (may include new transfer }   
  18958.                                   { modes)}    
  18959.       PixData:                    {described in Table 5}
  18960.  
  18961.   3.  pixMap:                     {described in Table 5 }
  18962.       colorTable:                 {described in Table 5 }
  18963.       srcRect:       Rect;        {source rectangle}
  18964.       dstRect:       Rect;        {destination rectangle}
  18965.       mode:          Word;        {transfer mode (may include new transfer }
  18966.                                   { modes)}   
  18967.       maskRgn:       Rgn;         {region for masking}
  18968.       PixData:                    {described in Table 5}
  18969.  
  18970.   4.  These four opcodes ($0090, $0091, $0098, $0099) are modifications of
  18971.       existing (version 1) opcodes.  The first word following the opcode is
  18972.       the rowBytes. If the high bit of the rowBytes is set, then it is a
  18973.       pixMap containing multiple bits per pixel; if it is not set, it is a
  18974.       bitMap containing one bit per pixel.  In general, the difference between
  18975.       version 1 and version 2 formats is that the pixMap replaces the bitMap,
  18976.       a color table has been added, and pixData replaces the bitData.
  18977.  
  18978.   5. Opcodes $0090 and $0091 are used only for rowbytes less than 8.
  18979.  
  18980. Table 5–Data Types Found Within New PICT Opcodes Listed in Table 4
  18981. _______________________________________________________________________________
  18982. Data Type     Field Definitions       Comments
  18983.  
  18984. pixMap     =  baseAddr:      long;    {unused = 0}
  18985.               rowBytes:      word;    {rowBytes w/high byte set}
  18986.               Bounds:        rect;    {bounding rectangle}
  18987.               version:       word;    {version number = 0}
  18988.               packType:      word;    {packing format = 0}
  18989.               packSize:      long;    {packed size = 0}
  18990.               hRes:          fixed;   {horizontal resolution (default = }
  18991.                                       { $0048.0000)}
  18992.               vRes:          fixed;   {vertical resolution (default= }
  18993.                                       { $0048.0000)}
  18994.               pixelType:     word;    {chunky format = 0}
  18995.               pixelSize:     word;    {# bits per pixel (1,2,4,8)}
  18996.               cmpCount:      word;    {# components in pixel = 1}
  18997.               cmpSize:       word;    {size of each component = pixelSize }
  18998.                                       { for chunky}
  18999.               planeBytes:    long;    {offset to next plane = 0}
  19000.               pmTable:       long;    {color table = 0}
  19001.               pmReserved:    long;    {reserved = 0}
  19002.               end;
  19003.  
  19004. colorTable =  ctSeed:        long;    {id number for color table = 0}
  19005.               ctFlags:       word;    {flags word = 0}
  19006.               ctSize:        word;    {number of ctTable entries-1 }
  19007.                                       { ctSize + 1 color table entries }
  19008.                                       { each entry = pixel value, red, }
  19009.                                       { green, blue: word}
  19010.               end;
  19011.  
  19012. pixData:  {the following pseudocode describes the pixData data type}
  19013.           If rowBytes < 8 then data is unpacked
  19014.               data size = rowBytes*(bounds.bottom-bounds.top);
  19015.           If rowBytes >= 8 then data is packed.
  19016.               Image contains (bounds.bottom-bounds.top) packed scanlines.
  19017.               Packed scanlines are produced by the PackBits routine.
  19018.               Each scanline consists of [byteCount] [data].
  19019.               If rowBytes > 250 then byteCount is a word,
  19020.                   else it is a byte.
  19021.               end;
  19022. _______________________________________________________________________________
  19023.  
  19024.  
  19025. æKY Summary…of…Color…QuickDraw
  19026. æC »SUMMARY OF COLOR QUICKDRAW                                 ColorQuickDraw
  19027. _______________________________________________________________________________
  19028.  
  19029. Constants
  19030.  
  19031. CONST
  19032.   { Old-style grafPort colors }
  19033.  
  19034.   blackColor   = 33;
  19035.   whiteColor   = 30;
  19036.   redColor     = 209;
  19037.   greenColor   = 329;
  19038.   blueColor    = 389;
  19039.   cyanColor    = 269;
  19040.   magentaColor = 149;
  19041.   yellowColor  = 89;
  19042.  
  19043.   { Arithmetic transfer modes }
  19044.  
  19045.   blend    = 32;
  19046.   addPin   = 33;
  19047.   addOver  = 34;
  19048.   subPin   = 35;
  19049.   adMax    = 37;
  19050.   subOver  = 38;
  19051.   adMin    = 39;
  19052.  
  19053.   { Transparent mode constant }
  19054.  
  19055.   transparent  = 36;
  19056.  
  19057.   { Text mask constant }
  19058.  
  19059.   mask     = 64;
  19060.  
  19061.   { Highlight constants }
  19062.  
  19063.   hilite      = 50;
  19064.   pHiliteBit  = 0;    {this is the correct value for use when }
  19065.                       { calling the BitClear trap. BClr must use }
  19066.                       { the assembly language equate hiliteBit}
  19067.  
  19068.   { Constant for resource IDs }
  19069.  
  19070.    defQDColors = 127;
  19071.  
  19072. _______________________________________________________________________________
  19073.  
  19074. Data Types
  19075.  
  19076. TYPE
  19077.   RGBColor  =  RECORD
  19078.                  red:    INTEGER;    {red component}
  19079.                  green:  INTEGER;    {green component}
  19080.                  blue:   INTEGER     {blue component}
  19081.                END;
  19082.  
  19083.   ColorSpec  =  RECORD
  19084.                   value:  INTEGER;    {index or other value}
  19085.                   rgb:    RGBColor    {true color}
  19086.                 END;
  19087.  
  19088.   cSpecArray : ARRAY [0..0] of ColorSpec;
  19089.  
  19090.   CTabHandle = ^CTabPtr;
  19091.   CTabPtr    = ^ColorTable;
  19092.   ColorTable = RECORD
  19093.                  ctSeed:   LONGINT;    {unique identifier from table}
  19094.                  ctFlags:  INTEGER;    {high bit is 1 for device, 0 }
  19095.                                        { for pixMap}
  19096.                  ctSize:   INTEGER;    {number of entries -1 in }
  19097.                                        { ctTable}
  19098.                  ctTable:  cSpecArray
  19099.                END;
  19100.  
  19101.   CGrafPtr  = ^CGrafPort;
  19102.   CGrafPort = RECORD
  19103.                 device:      INTEGER;       {device ID for font selection}
  19104.                 portPixMap:  PixMapHandle;  {port's pixel map}
  19105.                 portVersion: INTEGER;       {highest 2 bits always set}
  19106.                 grafVars:    Handle;        {handle to more fields}
  19107.                 chExtra:     INTEGER;       {extra characters placed}
  19108.                                             { on the end of a string}
  19109.                 pnLocHFrac:  INTEGER;       {pen fraction}
  19110.                 portRect:    Rect;          {port rectangle}
  19111.                 visRgn:      RgnHandle;     {visible region}
  19112.                 clipRgn:     RgnHandle;     {clipping region}
  19113.                 bkPixPat:    PixPatHandle;  {background pattern}
  19114.                 rgbFgColor:  RGBColor;      {requested foreground color}
  19115.                 rgbBkColor:  RGBColor;      {requested background color}
  19116.                 pnLoc:       Point;         {pen location}
  19117.                 pnSize:      Point;         {pen size}
  19118.                 pnMode:      INTEGER;       {pen transfer mode}
  19119.                 pnPixPat:    PixPatHandle;  {pen pattern}
  19120.                 fillPixPat:  PixPatHandle;  {fill pattern}
  19121.                 pnVis:       INTEGER;       {pen visibility}
  19122.                 txFont:      INTEGER;       {font number for text}
  19123.                 txFace:      Style;         {text's character style}
  19124.                 txMode:      INTEGER;       {text's transfer mode}
  19125.                 txSize:      INTEGER;       {font size for text}
  19126.                 spExtra:     Fixed;         {extra space}
  19127.                 fgColor:     LONGINT;       {actual foreground color}
  19128.                 bkColor:     LONGINT;       {actual background color}
  19129.                 colrBit:     INTEGER;       {plane being drawn}
  19130.                 patStretch:  INTEGER;       {used internally}
  19131.                 picSave:     Handle;        {picture being saved}
  19132.                 rgnSave:     Handle;        {region being saved}
  19133.                 polySave:    Handle;        {polygon being saved}
  19134.                 grafProcs:   CQDProcsPtr    {low-level drawing routines}
  19135.               END;
  19136.  
  19137.   GrafVars  =  RECORD
  19138.                  rgbOpColor:      RGBColor;  {color for addPin, }
  19139.                                              { subPin, and blend}
  19140.                  rgbHiliteColor:  RGBColor;  {color for hiliting}
  19141.                  pmFgColor:       Handle;    {palette handle for }
  19142.                                              { foreground color}
  19143.                  pmFgIndex:       INTEGER;   {index value for foreground}
  19144.                  pmBkColor:       Handle;    {palette handle for }
  19145.                                              { background color}
  19146.                  pmBkIndex:       INTEGER;   {index value for background}
  19147.                  pmFlags:         INTEGER;   {flags for Palette Manager}
  19148.                END;
  19149.  
  19150.   PixMapHandle = ^PixMapPtr;
  19151.   PixMapPtr    = ^PixMap;
  19152.   PixMap       = RECORD
  19153.                    baseAddr:   Ptr;         {pointer to pixMap data}
  19154.                    rowBytes:   INTEGER;     {offset to next row}
  19155.                    bounds:     Rect;        {boundary rectangle}
  19156.                    pmVersion:  INTEGER;     {color QuickDraw version number}
  19157.                    packType:   INTEGER;     {packing format}
  19158.                    packSize:   LONGINT;     {size of data in packed state}
  19159.                    hRes:       Fixed;       {horizontal resolution}
  19160.                    vRes:       Fixed;       {vertical resolution}
  19161.                    pixelType:  INTEGER;     {format of pixel image}
  19162.                    pixelSize:  INTEGER;     {physical bits per pixel}
  19163.                    cmpCount:   INTEGER;     {logical components per pixel}
  19164.                    cmpSize:    INTEGER;     {logical bits per component}
  19165.                    planeBytes: LONGINT;     {offset to next plane}
  19166.                    pmTable:    CTabHandle;  {absolute colors for this image}
  19167.                    pmReserved: LONGINT      {reserved for future expansion}
  19168.                  END;
  19169.  
  19170.   PixPatHandle = ^PixPatPtr;
  19171.   PixPatPtr    = ^PixPat;
  19172.   PixPat       = RECORD
  19173.                    patType:    INTEGER;       {pattern type}
  19174.                    patMap:     PixMapHandle;  {pattern characteristics}
  19175.                    patData:    Handle;        {pixel image defining pattern}
  19176.                    patXData:   Handle;        {expanded pixel image}
  19177.                    patXValid:  INTEGER;       {flags for expanded pattern data}
  19178.                    patXMap:    Handle;        {handle to expanded pattern data}
  19179.                    pat1Data:   Pattern;       {old-style pattern/RGB color}
  19180.                  END;
  19181.  
  19182.   CCrsrHandle = ^CCrsrPtr;
  19183.   CCrsrPtr    = ^CCrsr;
  19184.   CCrsr       = RECORD
  19185.                   crsrType:     INTEGER;       {type of cursor}
  19186.                   crsrMap:      PixMapHandle;  {the cursor's pixMap}
  19187.                   crsrData:     Handle;        {cursor's data}
  19188.                   crsrXData:    Handle;        {expanded cursor data}
  19189.                   crsrXValid:   INTEGER;       {depth of expanded data}
  19190.                   crsrXHandle:  Handle;        {reserved for future use}
  19191.                   crsr1Data:    Bits16;        {one-bit cursor}
  19192.                   crsrMask:     Bits16;        {cursor's mask}
  19193.                   crsrHotSpot:  Point;         {cursor's hotspot}
  19194.                   crsrXTable:   LONGINT;       {private}
  19195.                   crsrID:       LONGINT;       {ctSeed for expanded cursor}
  19196.                 END;
  19197.  
  19198.   CIconHandle = ^CIconPtr;
  19199.   CIconPtr    = ^CIcon;
  19200.   CIcon       = RECORD
  19201.                   iconPMap:     PixMap;    {the icon's pixMap}
  19202.                   iconMask:     BitMap;    {the icon's mask bitMap}
  19203.                   iconBMap:     BitMap;    {the icon's bitMap}
  19204.                   iconData:     Handle;    {the icon's data}
  19205.                   iconMaskData: ARRAY[0..0] OF INTEGER; {icon's }
  19206.                                            { mask and bitMap data}
  19207.                 END;
  19208.  
  19209.   MatchRec = RECORD
  19210.                red:        INTEGER;    {red component}
  19211.                green:      INTEGER;    {green component}
  19212.                blue:       INTEGER;    {blue component}
  19213.                matchData:  LONGINT;   
  19214.              END;
  19215.  
  19216.   CQDProcsPtr = ^CQDProcs
  19217.   CQDProcs    = RECORD
  19218.                   textProc:     Ptr;    
  19219.                   lineProc:     Ptr;    
  19220.                   rectProc:     Ptr;    
  19221.                   rRectProc:    Ptr;    
  19222.                   ovalProc:     Ptr;    
  19223.                   arcProc:      Ptr;    
  19224.                   polyProc:     Ptr;    
  19225.                   rgnProc:      Ptr;    
  19226.                   bitsProc:     Ptr;    
  19227.                   commentProc:  Ptr;    
  19228.                   txMeasProc:   Ptr;    
  19229.                   getPicProc:   Ptr;    
  19230.                   putPicProc:   Ptr;    
  19231.                   opcodeProc:   Ptr;    {fields added to QDProcs}
  19232.                   newProc1:     Ptr;    {reserved for future use}
  19233.                   newProc2:     Ptr;    {reserved for future use}
  19234.                   newProc3:     Ptr;    {reserved for future use}
  19235.                   newProc4:     Ptr;    {reserved for future use}
  19236.                   newProc5:     Ptr;    {reserved for future use}
  19237.                   newProc6:     Ptr;    {reserved for future use}
  19238.                 END;
  19239.  
  19240. _______________________________________________________________________________
  19241.  
  19242. Routines
  19243.  
  19244. Operations on cGrafPorts
  19245.  
  19246. PROCEDURE OpenCPort  (port: CGrafPtr);
  19247. PROCEDURE InitCPort  (port: CGrafPtr);
  19248. PROCEDURE CloseCPort (port: CGrafPtr);
  19249.  
  19250. Setting the Foreground and Background Colors
  19251.  
  19252. PROCEDURE RGBForeColor (color : RGBColor);
  19253. PROCEDURE RGBBackColor (color : RGBColor);
  19254. PROCEDURE GetForeColor (VAR color : RGBColor);
  19255. PROCEDURE GetBackColor (VAR color : RGBColor);
  19256.  
  19257. Creating Pixel Maps
  19258.  
  19259. FUNCTION NewPixMap : PixMapHandle;
  19260. PROCEDURE DisposPixMap (pm: PixMapHandle);
  19261. PROCEDURE CopyPixMap   (srcPM,dstPM: PixMapHandle);
  19262.  
  19263. Operations on Pixel Maps
  19264.  
  19265. PROCEDURE CopyBits  (srcBits, dstBits: BitMap; srcRect, dstRect: Rect;
  19266.                      mode: INTEGER; maskRgn: RgnHandle);
  19267. PROCEDURE CopyMask  (srcBits,maskBits,dstBits: BitMap;
  19268.                      srcRect, maskRect, dstRect: Rect);
  19269. PROCEDURE SeedCFill (srcBits, dstBits: BitMap;  srcRect, dstRect: Rect;
  19270.                      seedH, seedV: INTEGER; matchProc: ProcPtr;
  19271.                      matchData: LONGINT);
  19272. PROCEDURE CalcCMask (srcBits, dstBits: BitMap; srcRect, dstRect: Rect;
  19273.                      seedRGB: RGBColor; matchProc: ProcPtr; matchData: LONGINT);
  19274.  
  19275. Operations on Pixel Patterns
  19276.  
  19277. FUNCTION  NewPixPat : PixPatHandle;
  19278. PROCEDURE DisposPixPat (ppat: PixPatHandle);
  19279. FUNCTION  GetPixPat    (patID: INTEGER): PixPatHandle;
  19280. PROCEDURE CopyPixPat   (srcPP,dstPP: PixPatHandle);
  19281. PROCEDURE MakeRGBPat   (ppat: PixPatHandle; myColor: RGBColor);
  19282. PROCEDURE PenPixPat    (ppat: PixPatHandle);
  19283. PROCEDURE BackPixPat   (ppat: PixPatHandle);
  19284.  
  19285. Color Drawing Operations
  19286.  
  19287. PROCEDURE FillCRect      (r: Rect; ppat: PixPatHandle);
  19288. PROCEDURE FillCOval      (r: Rect; ppat: PixPatHandle);
  19289. PROCEDURE FillCRoundRect (r: Rect; ovWd,ovHt: INTEGER; ppat: PixPatHandle);
  19290. PROCEDURE FillCArc       (r: Rect; startAngle,arcAngle: INTEGER;
  19291.                           ppat: PixPatHandle);
  19292. PROCEDURE FillCRgn       (rgn: RgnHandle; ppat: PixPatHandle);
  19293. PROCEDURE FillCPoly      (poly: PolyHandle; ppat: PixPatHandle);
  19294. PROCEDURE GetCPixel      (h,v: INTEGER; VAR cPix: RGBColor);
  19295. PROCEDURE SetCPixel      (h,v: INTEGER; cPix: RGBColor);
  19296.  
  19297. Operations on Color Cursors
  19298.  
  19299. FUNCTION  GetCCursor    (crsrID: INTEGER): CCrsrHandle;
  19300. PROCEDURE SetCCursor    (cCrsr: CCrsrHandle);
  19301. PROCEDURE DisposCCursor (cCrsr: CCrsrHandle);
  19302. PROCEDURE AllocCursor;
  19303.  
  19304. Operations on Icons
  19305.  
  19306. FUNCTION  GetCIcon    (id: INTEGER): CIconHandle;
  19307. PROCEDURE DisposCIcon (theIcon: CIconHandle);
  19308. PROCEDURE PlotCIcon   (theRect: Rect; theIcon: CIconHandle);
  19309.  
  19310. Operations on cGrafPort Fields
  19311.  
  19312. PROCEDURE SetPortPix   (pm: PixMapHandle);
  19313. PROCEDURE OpColor      (color: RGBColor);
  19314. PROCEDURE HiliteColor  (color:RGBColor);
  19315. PROCEDURE CharExtra    (extra:Fixed);
  19316. PROCEDURE SetStdCProcs (VAR cProcs: CQDProcs);
  19317.  
  19318. Operations on Color Tables
  19319.  
  19320. FUNCTION  GetCTable    (ctID: INTEGER): CTabHandle;
  19321. PROCEDURE DisposCTable (ctTab: CTabHandle);
  19322.  
  19323. Color Picture Operations
  19324.  
  19325. FUNCTION OpenPicture (picFrame: Rect) : PicHandle;
  19326.  
  19327. _______________________________________________________________________________
  19328.  
  19329. Global Variables
  19330.  
  19331. HiliteMode    {if the hilite mode is set, highlighting is on}
  19332. HiliteRGB     {default highlight color for the system}
  19333.  
  19334. _______________________________________________________________________________
  19335.  
  19336. Assembly-Language Interface
  19337.  
  19338. HiLite Constant
  19339.  
  19340. hiliteBit    EQU    7    ;flag bit in HiliteMode
  19341.                          ; this is the correct value for use in assembler
  19342.                          ; programs
  19343.  
  19344. Equates for Resource IDs
  19345.  
  19346. defQDColors    EQU    127    ;resource ID of clut for default QDColors
  19347.  
  19348. RGBColor structure
  19349.  
  19350. red         EQU    $0    ;[word] red channel intensity   
  19351. green       EQU    $2    ;[word] green channel intensity   
  19352. blue        EQU    $4    ;[word] blue channel intensity   
  19353. rgbColor    EQU    $6    ;size of record
  19354.  
  19355. ColorSpec structure
  19356.  
  19357. value            EQU    $0    ;[short] value field
  19358. rgb              EQU    $2    ;[rgbColor] rgb values
  19359. colorSpecSize    EQU    $8    ;size of record
  19360.  
  19361. Additional Offsets in a cGrafPort
  19362.  
  19363. portPixMap     EQU    portBits         ;[long] pixelMap handle
  19364. portVersion    EQU    portPixMap+4     ;[word] port version number
  19365. grafVars       EQU    portVersion+2    ;[long] handle to new fields
  19366. chExtra        EQU    grafVars+4       ;[word] extra characters placed at
  19367.                                        ; the end of a string
  19368. pnLocHFrac     EQU    chExtra+2        ;[word] pen fraction
  19369.  
  19370. bkPixPat       EQU    bkPat            ;[long] handle to bk pattern
  19371. rgbFgColor     EQU    bkPixPat+4       ;[6 bytes] RGB components of fg color
  19372. rgbBkColor     EQU    RGBFgColor+6     ;[6 bytes] RGB components of bk color
  19373.  
  19374. pnPixPat       EQU    $3A              ;[long] handle to pen's pattern
  19375. fillPixPat     EQU    pnPixPat+4       ;[long] handle to fill pattern
  19376.  
  19377. Offsets Within GrafVars
  19378.  
  19379. rgbOpColor        EQU    0                   ;[6 bytes] color for addPin,
  19380.                                              ; subPin, and blend
  19381. rgbHiliteColor    EQU    rgbOpColor+6        ;[6 bytes] color for hiliting
  19382. pmFgColor         EQU    rgbHiliteColor+6    ;[4 bytes] Palette handle for
  19383.                                              ; foreground color
  19384. pmFgIndex         EQU    pmFgColor+4         ;[2 bytes] index value for
  19385.                                              ; foreground
  19386. pmBkColor         EQU    pmFgIndex+2         ;[4 bytes] Palette handle for
  19387.                                              ; background color
  19388. pmBkIndex         EQU    pmBkColor+4         ;[2 bytes] index value for
  19389.                                              ; background
  19390. pmFlags           EQU    pmBkIndex+2         ;[2 bytes] Flags for Palette
  19391.                                              ; manager
  19392. grafVarRec        EQU    pmFlags+2           ;size of grafVar record
  19393.  
  19394. PixMap field offsets
  19395.  
  19396. pmBaseAddr     EQU    $0    ;[long]
  19397. pmNewFlag      EQU    $4    ;[1 bit]  upper bit of rowbytes is flag
  19398. pmRowBytes     EQU    $4    ;[word]
  19399. pmBounds       EQU    $6    ;[rect]
  19400. pmVersion      EQU    $E    ;[word]   pixMap version number
  19401. pmPackType     EQU    $10   ;[word]   defines packing format
  19402. pmPackSize     EQU    $12   ;[long]   size of pixel data
  19403. pmHRes         EQU    $16   ;[fixed]  h. resolution (ppi)
  19404. pmVRes         EQU    $1A   ;[fixed]  v. resolution (ppi)
  19405. pmPixelType    EQU    $1E   ;[word]   defines pixel type
  19406. pmPixelSize    EQU    $20   ;[word]   # bits in pixel
  19407. pmCmpCount     EQU    $22   ;[word]   # components in pixel
  19408. pmCmpSize      EQU    $24   ;[word]   # bits per field
  19409. pmPlaneBytes   EQU    $26   ;[long]   offset to next plane
  19410. pmTable        EQU    $2A   ;[long]   color map
  19411. pmReserved     EQU    $2E   ;[long]   must be 0
  19412. pmRec          EQU    $32   ; size of pixMap record
  19413.  
  19414. PixPat field offsets
  19415.  
  19416. patType      EQU    $0    ;[word] type of pattern
  19417. patMap       EQU    $2    ;[long] handle to pixmap
  19418. patData      EQU    $6    ;[long] handle to data
  19419. patXData     EQU    $A    ;[long] handle to expanded pattern data
  19420. patXValid    EQU    $E    ;[word] flags whether expanded pattern valid
  19421. patXMap      EQU    $10   ;[long] handle to expanded pattern data
  19422. pat1Data     EQU    $14   ;[8 bytes] old-style pattern/RGB color
  19423. ppRec        EQU    $1C   ; size of pixPat record
  19424.  
  19425. Pattern Types
  19426.  
  19427. oldPat       EQU    0        ;foreground/background pattern
  19428. newPat       EQU    1        ;self-contained color pattern
  19429. ditherPat    EQU    2        ;rgb value to be dithered
  19430. oldCrsrPat   EQU    $8000    ;old-style cursor
  19431. CCrsrPat     EQU    $8001    ;new-style cursor
  19432.  
  19433. CCrsr (Color Cursor) field offsets
  19434.  
  19435. crsrType      EQU    0              ;[word] cursor type
  19436. crsrMap       EQU    crsrType+2     ;[long] handle to cursor's pixmap
  19437. crsrData      EQU    crsrMap+4      ;[long] handle to cursor's color data
  19438. crsrXData     EQU    crsrData+4     ;[long] handle to expanded data
  19439. crsrXValid    EQU    crsrXData+4    ;[word] handle to expanded data (0 if none)
  19440. crsrXHandle   EQU    crsrXValid+2   ;[long] handle for future use
  19441. crsr1Data     EQU    crsrXHandle+4  ;[16 words] one-bit data
  19442. crsrMask      EQU    crsr1Data+32   ;[16 words] one-bit mask
  19443. crsrHotSpot   EQU    crsrMask+32    ;[point] hot-spot for cursor
  19444. crsrXTable    EQU    crsrHotSpot+4  ;[long] private
  19445. crsrID        EQU    crsrXTable+4   ;[long] color table seed for
  19446.                                     ; expanded cursor
  19447. crsrRec       EQU    crsrID+4       ;size of cursor save area
  19448.  
  19449. CIcon (Color Icon) field offsets
  19450.  
  19451. iconPMap    EQU    0                   ;[pixmap] icon's pixMap
  19452. iconMask    EQU    iconPMap+pmRec      ;[bitmap] 1-bit version of icon
  19453.                                        ; 1-bit mask
  19454. iconBMap    EQU    iconMask+bitmapRec  ;[bitmap] 1-bit version of icon
  19455. iconData    EQU    iconBMap+bitmapRec  ;[long] Handle to pixMap data
  19456.                                        ; followed by bMap and mask data
  19457. iconRec     EQU    iconData+4          ;size of icon header
  19458.  
  19459. Extensions to the QDProcs record
  19460.  
  19461. opcodeProc   EQU  $34     ;[pointer]
  19462. newProc1     EQU  $38     ;[pointer]
  19463. newProc2     EQU  $3C     ;[pointer]
  19464. newProc3     EQU  $40     ;[pointer]
  19465. newProc4     EQU  $44     ;[pointer]
  19466. newProc5     EQU  $48     ;[pointer]
  19467. newProc6     EQU  $4C     ;[pointer]
  19468. cqdProcsRec  EQU  $50     ; size of QDProcs record
  19469.  
  19470. MatchRec structure
  19471.  
  19472. red           EQU    $0    ; [word] defined in RGBColor
  19473. green         EQU    $2    ; [word] defined in RGBColor
  19474. blue          EQU    $4    ; [word] defined in RGBColor
  19475. matchData     EQU    $6    ; [long]
  19476. matchRecSize  EQU    $A    ;size of record
  19477.  
  19478. Global Variables
  19479.  
  19480. HiliteMode    EQU    $938    ;if the hilite bit is set, highlighting is on
  19481. HiliteRGB     EQU    $DA0    ;default highlight color for the system
  19482.  
  19483. Further Reference:
  19484. _______________________________________________________________________________
  19485. QuickDraw
  19486. Graphics Devices
  19487. Color Manager
  19488. Color Picker Package
  19489. Palette Manager
  19490. Resource Manager
  19491. Technical Note #21, QuickDraw’s Internal Picture Definition
  19492. Technical Note #27, MacDraw’s PICT File Format
  19493. Technical Note #120, Drawing Into an Off-Screen Pixel Map
  19494. Technical Note #163, Adding Color With CopyBits
  19495. Technical Note #171, _PackBits Data Format
  19496. Technical Note #244, A Leading Cause of Color Cursor Cursing
  19497. 32-Bit QuickDraw Documentation
  19498.  
  19499. æKY CompatibilityGuidelines
  19500. æC 
  19501. _______________________________________________________________________________
  19502.  
  19503. COMPATIBILITY GUIDELINES
  19504. _______________________________________________________________________________
  19505.  
  19506. About…the…Compatibility…Guidelines…Vol…VI…Chapter
  19507. About…Compatibility…Vol…VI
  19508.     Using…Memory…Wisely
  19509.     Using…Assembly…Language
  19510.     Accessing…Hardware
  19511.     Using…Low-Memory…Global…Variables
  19512.     Determining…Whether…a…Trap…Is…Available
  19513. Running…in…System…Software…Version…7.0
  19514.     Allowing…Multiple…Applications
  19515.     Supporting…Standard…AppleEvents
  19516.     Selecting…AppleEvents…to…Support
  19517.     Isolating…User…Interface…Code
  19518.     Modifying…the…Event…Loop
  19519.     Indicating…an…Application…Is…AppleEvent-Aware
  19520.     Removing…Font…Size…Restrictions
  19521.     Operating…With…Virtual…Memory
  19522. Localizing…Macintosh…Programs
  19523.     General…Guidelines…for…Compatibility
  19524.     Other…Localization…Tools
  19525. Running…Macintosh…Programs…Under…A/UX
  19526.     How…the…A/UX…Toolbox…Works
  19527.     Using…the…A/UX…Toolbox
  19528.     A/UX…Compatibility…Guidelines
  19529. About…the…Gestalt…Manager
  19530. Using…the…Gestalt…Manager
  19531.     Determining…Features…of…the…Operating…Environment
  19532.     Determining…Whether…Gestalt…Is…Available
  19533.     Interpreting…Gestalt…Responses
  19534.     Interpreting…Responses…to…Environmental…Selectors
  19535.     Interpreting…Responses…to…Informational…Selectors
  19536.     Adding…Gestalt…Selectors
  19537.     Modifying…Gestalt…Selectors
  19538.     Specifying…Gestalt…Selector…Functions
  19539. Gestalt…Manager…Routines
  19540.     Getting…Information…About…the…Operating…Environment
  19541.     Adding…Selector…Codes
  19542.     Modifying…Selector…Codes
  19543. Summary…of…the…Gestalt…Manager
  19544.     Gestalt…Manager…Constants
  19545.     Gestalt…Manager…Routines…Summary
  19546.     Gestalt…Manager…Result…Codes
  19547.  
  19548. About…The…CompatibilityGuide…Chapter
  19549. Compatibility
  19550. Determining…the…Features…of…a…Machine
  19551. Localization
  19552. Applications…in…a…Shared…Environment
  19553. Summary…of…Compatability…Guidelines
  19554. _______________________________________________________________________________
  19555.  
  19556.  
  19557.  
  19558. æKY About…the…Compatibility…Guidelines…Vol…VI…Chapter
  19559. æC »ABOUT THIS CHAPTER                                            Compatibility Guidelines
  19560. _______________________________________________________________________________
  19561.  
  19562. This chapter describes how you can write applications that have the greatest
  19563. chance of operating on all models of the Macintosh® computer, regardless of the
  19564. hardware components found on any particular machine and of the available system
  19565. software, managers, and device drivers. It addresses how you can take advantage
  19566. of features that are new to system software version 7.0 in ways that are least
  19567. likely to cause problems for users who are not running version 7.0. In a word,
  19568. this chapter provides as much advice as possible to help you achieve maximum
  19569. compatibility for your applications on all Macintosh computers, including those
  19570. running version 7.0.
  19571.  
  19572. System software version 7.0 provides the most important test of software
  19573. compatibility since the introduction of the Macintosh II, and you must
  19574. understand how you may need to revise your current applications so that they
  19575. operate correctly with this new system software. Fortunately, if you have
  19576. followed the guidelines given in previous volumes of Inside Macintosh, your
  19577. applications stand a very good chance of working correctly in version 7.0
  19578. without any modification whatsoever. However, version 7.0 introduces many new
  19579. features and capabilities that you may wish to use in your applications, without
  19580. sacrificing compatibility with earlier versions of system software. This chapter
  19581. provides a number of additional guidelines to help you revise existing
  19582. applications to take advantage of version 7.0 features while retaining
  19583. compatibility with previous system software.
  19584.  
  19585. System software version 7.0, with its multitasking environment and its new
  19586. emphasis on communication and cooperation among applications, places certain
  19587. responsibilities on applications. As a result, you must be more aware than ever
  19588. of the programming shortcuts that can result in incompatibility.
  19589.  
  19590. This chapter focuses on several aspects of writing software that is compatible
  19591. with all Macintosh computers:
  19592.  
  19593.   •   what can cause compatibility problems and how in general to avoid those
  19594.       problems
  19595.  
  19596.   •   how to write applications that execute in both version 6.0 and version
  19597.       7.0 system software
  19598.  
  19599.   •   how to determine what software and hardware features are available on a
  19600.       particular machine
  19601.  
  19602.   •   how to write applications that execute under A/UX®, Apple’s version of
  19603.       the UNIX® operating system
  19604.  
  19605.   •   how to write software that can be easily modified for use in other
  19606.       countries
  19607.  
  19608. This chapter also describes the Gestalt Manager, a set of three new Operating
  19609. System functions that provide applications with a simple and efficient method
  19610. for determining what software and hardware features are available on a given
  19611. machine. You need to use the Gestalt Manager if your application takes advantage
  19612. of particular hardware components (such as a floating-point unit) or software
  19613. modules (such as Color QuickDraw™) that are not available on all Macintosh
  19614. computers. Your application can also use the Gestalt Manager to inform the
  19615. Operating System (and hence other applications) that it is present in the
  19616. current environment.
  19617.  
  19618. The Gestalt Manager is available in system software version 7.0. It is also
  19619. included in system software versions 6.0.4 and 6.0.5, and in ROM on two
  19620. machines, the Macintosh IIci and the Macintosh Portable. Your development system
  19621. may supply code that allows you to call Gestalt on earlier system software
  19622. versions; check the documentation provided with your development system to see
  19623. if this is possible. Of course, since you cannot use Gestalt to determine if it
  19624. is present, you must do that in some other way; one such method is illustrated
  19625. in 
  19626. “Determining Whether Gestalt Is Available” later in this chapter.
  19627.  
  19628. You need to read this chapter if you are interested in writing applications that
  19629. execute on as many Macintosh computers as possible or under alternate operating
  19630. systems such as A/UX. In particular, if you wish to enhance an existing product
  19631. so that it supports new features of system software version 7.0 but also
  19632. executes correctly in earlier versions of system software, or if you wish to
  19633. write a new product that executes only in version 7.0, you should look at 
  19634. “Running In System Software Version 7.0.” You should read the sections on the
  19635. Gestalt Manager later in this chapter if you need to take advantage of specific
  19636. software or hardware features that may not be present on all versions of the
  19637. Macintosh, or if you wish to inform other applications of the presence of your
  19638. application in the operating environment.
  19639.  
  19640. If you want your applications to run in system software versions earlier than
  19641. 6.0.4 (where the Gestalt function is not available), you should be familiar with
  19642. the Environs procedure, discussed in the Operating System Utilities chapter of
  19643. Volumes II and IV, and the SysEnvirons function, discussed in the Compatibility
  19644. Guidelines chapter of Volume V. Both Environs and SysEnvirons perform the kind
  19645. of function that Gestalt performs—they allow you to determine what features are
  19646. available on a specific machine. For reasons outlined later, however, you should
  19647. not use either of these routines if the Gestalt function is available.
  19648.  
  19649. Unfortunately, no single chapter can provide all the information you need to
  19650. achieve the greatest possible compatibility for your applications. Most of the
  19651. subsequent chapters in this volume (and indeed all previous volumes of Inside
  19652. Macintosh) contain numerous warnings and guidelines that you should heed if you
  19653. wish to increase the likelihood that your applications will execute correctly on
  19654. all members of the Macintosh family and under alternate operating systems such
  19655. as A/UX. The Memory Management chapter in this volume, for example, contains a
  19656. fuller account of 32-bit clean programming than is given here and is essential
  19657. reading for all developers. (An application is 32-bit clean if it can use all 32
  19658. bits of a handle or pointer for memory addressing.) Similarly, the guidelines
  19659. given in this chapter on writing A/UX-compatible Macintosh programs summarize
  19660. and complement, but do not replace, the discussion in the separate publication 
  19661. A/UX Toolbox: Macintosh ROM Interface. So the complete story on Macintosh
  19662. software compatibility does not end with this chapter, but it does begin here.
  19663.  
  19664. _______________________________________________________________________________
  19665.  
  19666. æKY About…Compatibility…Vol…VI
  19667. æC »ABOUT COMPATIBILITY                                           Compatibility Guidelines
  19668. _______________________________________________________________________________
  19669.  
  19670. Compatibility is the ability of a program to execute properly in different
  19671. operating environments. Compatibility is important if you want to write software
  19672. that runs, with little or no modification, on all members of the Macintosh
  19673. family and in all system software versions. If you want to take advantage of
  19674. particular software or hardware features that may not be present on all
  19675. Macintosh computers, you need to know how to determine when those features are
  19676. available.
  19677.  
  19678. To appreciate why compatibility is a real and sometimes vexing concern, imagine
  19679. that from all the Macintosh computers currently in operation in the world, you
  19680. were to choose two at random. You would quite likely find a great number of
  19681. differences in the hardware and software configurations on those two machines.
  19682. You might find different CPUs, different memory management units (MMUs),
  19683. different amounts of RAM, different shapes and sizes of monitors, and so forth.
  19684. You are also likely to find different versions of system software, different ROM
  19685. versions, different AppleTalk® drivers, different versions of managers,
  19686. different printer interfaces, and so forth. Ideally, you want your product to
  19687. run on both of those machines, regardless of the many significant differences
  19688. between them. If you succeed in writing your application so that it does operate
  19689. on both of those machines, you have succeeded in writing compatible software.
  19690.  
  19691. This section provides a number of guidelines that you should follow if you want
  19692. your applications to run on the greatest number of Macintosh computers. Some of
  19693. these guidelines are quite general and apply to all programs; some apply only if
  19694. you are programming in assembly language.
  19695.  
  19696. One key to achieving compatibility is not to depend on things that may change.
  19697. Inside Macintosh contains numerous warnings about which information is likely to
  19698. change. As the Operating System and User Interface Toolbox evolve to accommodate
  19699. the needs of developers and users, many of the elements will vary. Whenever
  19700. possible, Apple strives to add features without altering existing interfaces. In
  19701. general, you can assume that Operating System and Toolbox routines are less
  19702. likely to change than data structures. Therefore, you should never manipulate
  19703. data structures directly, even if their structure is documented. Instead, you
  19704. should manipulate those structures only indirectly, by calling Operating System
  19705. and Toolbox routines that achieve the desired effect. In particular, you should
  19706. never alter any portion of a data structure marked as unused or reserved.
  19707.  
  19708. Another key to writing compatible code is to code defensively. Do not assume
  19709. that users perform actions in a particular order, and do not assume that
  19710. function and procedure calls always succeed. You should always test the return
  19711. values of routines for errors, as illustrated in most of the code samples
  19712. presented in this volume.
  19713.  
  19714. _______________________________________________________________________________
  19715.  
  19716. æKY Using…Memory…Wisely
  19717. æC »Using Memory Wisely                                           Compatibility Guidelines
  19718. _______________________________________________________________________________
  19719.  
  19720. A major cause of compatibility problems, especially in connection with
  19721. applications running in the A/UX operating system, is misuse of the Memory
  19722. Manager . Here are some important points to keep in mind:
  19723.  
  19724.   • Do not set bits in master pointers directly. Use Memory Manager traps (for
  19725.     example, HLock) instead.
  19726.  
  19727.   • Always check the handle or pointer returned by a routine to make certain
  19728.     that it is not NIL. A NIL handle may indicate that a memory allocation
  19729.     failed, or that a requested resource could not be found.
  19730.  
  19731.   • Always check that a handle marked as purgeable has not been purged before
  19732.     using that handle. For example:
  19733.  
  19734.       IF myHandle^ <> NIL THEN  {handle not purged}
  19735.  
  19736.   • Do not create your own handles; instead, use the Memory Manager function
  19737.     NewHandle.
  19738.  
  19739.   • Never make assumptions about the contents of Memory Manager data structures.
  19740.  
  19741. If you have followed all these guidelines, it is likely that your application is
  19742. 32-bit clean, that is, that it operates correctly in an environment where all 32
  19743. bits of handles and pointers are used to store memory addresses. In system
  19744. software version 7.0 and A/UX, your applications must be 32-bit clean or they
  19745. may not operate correctly. See the Memory Management chapter in this volume for
  19746. more information about these points.
  19747.  
  19748. _______________________________________________________________________________
  19749.  
  19750. æKY Using…Assembly…Language
  19751. æC »Using Assembly Language                                       Compatibility Guidelines
  19752. _______________________________________________________________________________
  19753.  
  19754. In general, your software should not include 68000 instructions that require the
  19755. processor to be in supervisor mode; these include instructions that modify the
  19756. contents of the Status Register (SR). Programmers typically modify the SR only
  19757. as a means of changing the Condition Code Register (CCR) half of the SR; in
  19758. these cases, an instruction that addresses the CCR directly will work instead.
  19759. Do not use the User Stack Pointer or turn interrupts on and off.
  19760.  
  19761. If you wish to handle your own exceptions (thereby relying on the position of
  19762. data in the exception’s local stack frame), be aware that exception stack frames
  19763. vary within the 68000 family.
  19764.  
  19765. In particular, don’t use the TRAP instruction. Also, the TAS instruction, which
  19766. uses a special read-modify-write memory cycle, is not supported by the Macintosh
  19767. SE and Macintosh II hardware.
  19768.  
  19769. A memory management unit available in some Macintosh computers may prevent code
  19770. from writing to addresses within code segments. Also, the 68020 and 68030 cache
  19771. code as it is encountered. You should allocate data blocks on the stack or in
  19772. heap blocks separate from the code, and your code should not modify itself.
  19773.  
  19774. _______________________________________________________________________________
  19775.  
  19776. æKY Accessing…Hardware
  19777. æC »Accessing Hardware                                            Compatibility Guidelines
  19778. _______________________________________________________________________________
  19779.  
  19780. You should never address hardware directly; whenever possible, use the routines
  19781. provided by the various device drivers and managers to send data to the
  19782. available hardware. The addresses of memory-mapped hardware (like the VIA1,
  19783. VIA2, SCC, and so forth) are always subject to change, as is the hardware
  19784. itself. More important, direct access to such hardware is not possible in every
  19785. operating environment. In multiuser systems like A/UX, for instance, the
  19786. operating system manipulates all hardware; applications simply cannot write
  19787. directly to hardware addresses.
  19788.  
  19789. You should also avoid writing directly to the screen. Use QuickDraw routines
  19790. whenever possible to draw on the screen. If you absolutely must write directly
  19791. to the screen, do not assume that the screen is a fixed size or that it is in a
  19792. fixed location. The location, size, and bit depth of the screen differ in
  19793. various machines. Instead, you should read the QuickDraw global variable
  19794. screenBits.bounds to determine the size of the screen, screenBits.baseAddr to
  19795. determine the start of the screen, and screenBits.rowBytes to determine the
  19796. offset between rows. On machines with Color QuickDraw, the device list 
  19797. (described in the Graphics Devices chapter in this volume) tells the location,
  19798. size, and bit depth of each screen, screenBits contains the location and size of
  19799. the main device, and GrayRgn contains a region describing the shape and size of
  19800. the desktop.
  19801.  
  19802. _______________________________________________________________________________
  19803.  
  19804. æKY Using…Low-Memory…Global…Variables
  19805. æC »Using Low-Memory Global Variables                             Compatibility Guidelines
  19806. _______________________________________________________________________________
  19807.  
  19808. Don’t rely on low-memory global variables. Many of these variables have been
  19809. previously documented in Inside Macintosh, but many have not. In particular, you
  19810. must avoid undocumented low-memory global variables, because they are most
  19811. likely to change. But you should even avoid well-known global variables, since
  19812. they may not be available in all environments or in the future. In general, you
  19813. can avoid using low-memory global variables by using available routines that
  19814. return the same information. For example, the TickCount function returns the
  19815. same value that is contained in the low-memory global variable Ticks. TickCount
  19816. is available under A/UX, but Ticks is not. So you can increase the likelihood of
  19817. compatibility with A/UX by using the routine and not the global variable.
  19818.  
  19819. _______________________________________________________________________________
  19820.  
  19821. æKY Determining…Whether…a…Trap…Is…Available
  19822. æC »Determining Whether a Trap Is Available                       Compatibility Guidelines
  19823. _______________________________________________________________________________
  19824.  
  19825. One important way that the Operating System and Toolbox have changed through
  19826. successive versions of the ROM and system software is by the addition of
  19827. numerous new traps. For example, the Time Manager released with system software
  19828. version 7.0 includes a new trap, InsXTime, that provides certain improvements
  19829. over the existing trap, InsTime. By using InsXTime instead of InsTime, your
  19830. application can ensure that the periodic actions it requests will execute at a
  19831. fixed frequency that does not drift over time. Before using a trap that is not
  19832. available on all machines, however, you need to determine whether it is
  19833. available; if you call InsXTime on a machine that does not implement it, your
  19834. program will crash.
  19835.  
  19836. Your application can check the availability of a particular trap such as
  19837. InsXTime in one of two ways. First, you can call the Gestalt function that is
  19838. discussed later in this chapter to see if the appropriate version of the
  19839. corresponding driver or manager is available. For example, the trap InsXTime is
  19840. included in the extended Time Manager but not in earlier versions of the Time
  19841. Manager. So you could use Gestalt to determine which version of the Time Manager
  19842. is available in the current operating environment. If Gestalt reports that the
  19843. extended Time Manager is present, you can safely call InsXTime to queue your
  19844. request.
  19845.  
  19846. There are several cases, however, in which you cannot use Gestalt to determine
  19847. whether a specific trap is implemented. You cannot, for instance, use Gestalt to
  19848. determine whether the Gestalt trap itself is available. In addition, the trap
  19849. whose existence you wish to test might not be included in any manager or, if it
  19850. is, there might not be a Gestalt selector code for that manager. The
  19851. WaitNextEvent trap is a good example of this: there is no way, using Gestalt, to
  19852. determine whether WaitNextEvent is available.
  19853.  
  19854. The second way to determine the availability of a particular Operating System or
  19855. Toolbox trap is by testing directly for the existence of the trap, using the
  19856. technique illustrated in Listing 3-1. You should use this method to test whether
  19857. Gestalt is available before calling Gestalt. You should also use it to test for
  19858. the existence of traps not included in managers or drivers about which Gestalt
  19859. can report. This listing illustrates how to test the availability of
  19860. WaitNextEvent.
  19861.  
  19862. Listing 3-1.  Determining whether a trap is available
  19863.  
  19864. USES
  19865.   Types, Traps, OSUtils;
  19866.  
  19867. FUNCTION NumToolboxTraps: Integer;
  19868. BEGIN
  19869.   IF NGetTrapAddress(_InitGraf,ToolTrap) = 
  19870.         NGetTrapAddress($AA6E,ToolTrap) THEN
  19871.     NumToolboxTraps := $200
  19872.   ELSE
  19873.     NumToolboxTraps := $400;
  19874. END;
  19875.  
  19876. FUNCTION GetTrapType(theTrap: Integer): TrapType;
  19877. CONST
  19878.   TrapMask = $0800;
  19879. BEGIN
  19880.   IF BAND(theTrap,TrapMask) > 0 THEN
  19881.     GetTrapType := ToolTrap
  19882.   ELSE
  19883.     GetTrapType := OSTrap;
  19884. END;
  19885.  
  19886. FUNCTION TrapAvailable(theTrap: Integer): Boolean;
  19887. VAR
  19888.   tType: TrapType;
  19889. BEGIN
  19890.   tType := GetTrapType(theTrap);
  19891.   IF tType = ToolTrap THEN BEGIN
  19892.     theTrap := BAND(theTrap, $07FF);
  19893.     IF theTrap >= NumToolboxTraps THEN
  19894.       theTrap := _Unimplemented;
  19895.   END;
  19896.   TrapAvailable := NGetTrapAddress(theTrap, tType) <>
  19897.         NGetTrapAddress(_Unimplemented, ToolTrap);
  19898. END;
  19899.  
  19900. FUNCTION WNEAvailable: Boolean;
  19901. CONST
  19902.   _WaitNextEvent   =  $A860;  {trap number of WaitNextEvent}
  19903. BEGIN
  19904.   WNEAvailable :=  TrapAvailable(_WaitNextEvent);
  19905. END;
  19906.  
  19907. The NumToolboxTraps function relies on the fact that the InitGraf trap (trap
  19908. number $A86E) is always implemented. If the trap dispatch table is large enough 
  19909. (that is, has more than $200 entries), then $AA6E always points to either
  19910. Unimplemented or something else, but never to InitGraf. As a result, you can
  19911. check the size of the trap dispatch table by checking to see if the address of
  19912. trap $A86E is the same as $AA6E.
  19913.  
  19914. The TrapAvailable function uses the information about the size of the dispatch
  19915. table as follows: TrapAvailable first checks to see if the trap to be tested has
  19916. a trap number greater than the total number of traps available on the machine.
  19917. If so, then it sets theTrap to Unimplemented before testing it against the
  19918. Unimplemented trap.
  19919.  
  19920. Note:  The technique presented in Listing 3-1 for determining whether a
  19921. particular trap is available differs from techniques previously supported by
  19922. Apple. The previous method determined the size of the trap dispatch table by
  19923. checking the machine type. This type of check should not be used for any
  19924. purposes other than simply displaying the information, as explained in “Using
  19925. the Gestalt Manager.”  
  19926. _______________________________________________________________________________
  19927.  
  19928. æKY Running…in…System…Software…Version…7.0
  19929. æC »RUNNING IN SYSTEM SOFTWARE VERSION 7.0                        Compatibility Guidelines
  19930. _______________________________________________________________________________
  19931.  
  19932. You should keep in mind the guidelines given in the previous sections whenever
  19933. you are writing or revising any Macintosh application. If you heed those
  19934. guidelines, you are likely to produce applications that run reasonably well in
  19935. all environments, including system software version 7.0. So those guidelines
  19936. define a minimal level of conformance necessary for your applications to run in
  19937. version 7.0. Applications that conform to the programming interfaces documented
  19938. in Inside Macintosh and that violate none of the guidelines presented earlier in
  19939. this chapter are called 7.0-compatible because they run in version 7.0 without
  19940. problems.
  19941.  
  19942. An application can be 7.0-compatible, however, without taking advantage of the
  19943. many new features available in system software version 7.0 and without
  19944. exhibiting an awareness that other applications may be present and may wish to
  19945. use processor time that would otherwise go unused. Among those that do take
  19946. advantage of such features, there are at least two levels of involvement with
  19947. version 7.0. An application is 7.0-friendly if it takes advantage of some of the
  19948. special features of version 7.0 when executing under that environment, but is
  19949. still able to perform all its principal functions when executing in version 6.0.
  19950. An application is 7.0-dependent if it requires the existence of features that
  19951. are available only in version 7.0; it might not even run in version 6.0. Even if
  19952. 7.0-dependent applications do execute in version 6.0, they are virtually
  19953. guaranteed to offer far fewer features there than in version 7.0. A good example
  19954. of a 7.0-dependent application is a multimedia application that needs to do
  19955. real-time mixing of multiple channels of stereo sound. The Sound Manager
  19956. included with system software version 7.0 provides support for stereo output and
  19957. the ability to mix multiple independent channels of sampled sound; neither of
  19958. these features is available, however, with the Sound Manager provided with
  19959. version 6.0 or earlier.
  19960.  
  19961. The situation is similar to deciding whether your applications should use Color
  19962. QuickDraw. If you revise existing black-and-white drawing programs to
  19963. incorporate color, your applications operate either with or without Color
  19964. QuickDraw. If you introduce new applications that require Color QuickDraw, they
  19965. simply do not run on machines that don’t support color.
  19966.  
  19967. The rest of this section gives guidelines on what you can do to existing
  19968. applications to make them 7.0-friendly and not simply 7.0-compatible. The
  19969. following pages describe in overview how to
  19970.  
  19971.   •   be aware that the user may have launched multiple applications
  19972.  
  19973.   •   support the minimal set of required AppleEvents™
  19974.  
  19975.   •   remove font size restrictions to support outline fonts
  19976.  
  19977.   •   make sure that your application operates correctly with virtual memory
  19978.  
  19979. For complete details on any of these items, see the corresponding chapter in
  19980. this volume. For example, to learn what you need to do to support outline fonts
  19981. in your application, see the Font Manager chapter. (The information about
  19982. cooperating with other open applications is found in the Event Manager chapter.)
  19983.  
  19984. _______________________________________________________________________________
  19985.  
  19986. æKY Allowing…Multiple…Applications
  19987. æC »Allowing Multiple Applications                                Compatibility Guidelines
  19988. _______________________________________________________________________________
  19989.  
  19990. System software version 7.0 continues the development of the Macintosh Operating
  19991. System into a multitasking environment in which multiple applications can be
  19992. active and must share the available system resources. The facilities provided
  19993. with earlier versions of system software by the optional MultiFinder™ package
  19994. are now an integral part of system software version 7.0. This means that your
  19995. application must display a certain awareness that other applications might be
  19996. open at the same time and competing with it for processing time, memory, control
  19997. of communications ports, and so forth.
  19998.  
  19999. Although most operating systems regulate the sharing of available resources by
  20000. having the system parcel them out, the Macintosh Operating System relies on the
  20001. willingness of foreground and background applications to share those resources
  20002. among themselves. For example, each application must determine its own memory
  20003. requirements by specifying a minimum memory partition size (below which that
  20004. application does not execute) and a preferred partition size (at which the
  20005. application executes best). The Operating System itself has very little control
  20006. over the partition size allotted to the application, other than by limiting that
  20007. size to the available memory. Similarly, the Operating System has very little
  20008. control over which applications receive processing time, since the user
  20009. ultimately decides when to bring a background application into the foreground.
  20010. If your application holds onto the microprocessor for too long while being
  20011. switched into the background, other applications may appear sluggish and
  20012. unresponsive.
  20013.  
  20014. The lesson to be learned from all this is that, in system software version 7.0,
  20015. your application must be a good neighbor. You cannot expect the Operating System
  20016. to force responsible behavior on your application; rather, you must ensure that
  20017. your application can happily coexist with other open applications by following
  20018. these guidelines:
  20019.  
  20020.   •   include a 'SIZE' resource that specifies reasonable minimum and preferred
  20021.       memory partition sizes; if you occasionally need larger amounts of
  20022.       memory, use the temporary memory routines described in the Memory
  20023.       Management chapter
  20024.  
  20025.   •   use WaitNextEvent instead of GetNextEvent in your main event loop to
  20026.       obtain events from the Toolbox Event Manager; this allows other
  20027.       applications to use processor time your application doesn’t need, and
  20028.       allows your application to perform operations while it is in the
  20029.       background
  20030.  
  20031.   •   modify your main event loop to process suspend and resume events; this
  20032.       reduces the time it takes to switch your application into the foreground
  20033.       or background
  20034.  
  20035. For a more complete discussion of using WaitNextEvent and processing suspend and
  20036. resume events, see the Event Manager chapter in this volume. That chapter also
  20037. includes a description of the multitasking environment that is standard in
  20038. system software version 7.0.
  20039.  
  20040. _______________________________________________________________________________
  20041.  
  20042. æKY Supporting…Standard…AppleEvents
  20043. æC »Supporting Standard AppleEvents                               Compatibility Guidelines
  20044. _______________________________________________________________________________
  20045.  
  20046. Possibly the most significant new feature in system software version 7.0 is
  20047. interapplication communication (IAC), which will play an increasingly important
  20048. role in future versions of the Macintosh Operating System. One central part of
  20049. IAC is the addition of high-level events to those events that the Event Manager
  20050. receives and conveys to applications. High-level events allow applications to
  20051. communicate with one another by putting events in the event queue of the
  20052. receiving application.
  20053.  
  20054. Apple has defined a standard set of such high-level events, known as
  20055. AppleEvents, that are common to all or nearly all applications. Some AppleEvents
  20056. must be supported by an application that supports any AppleEvents; these are
  20057. known as required AppleEvents. With a minimal amount of work, you can modify
  20058. your main event loop so it supports the required AppleEvents. In doing so, you
  20059. increase the level of compatibility of your application and ease the transition
  20060. to the days when applications expect other applications to support AppleEvents.
  20061.  
  20062. There are four main steps you need to follow to incorporate support for the
  20063. required AppleEvents into your application: 
  20064.  
  20065. 1.  Identify the AppleEvents that you want your application to support.
  20066.  
  20067. 2.  Separate code that interacts with users from code that performs operations,
  20068.     whether requested by the user or by the required AppleEvents.
  20069.  
  20070. 3.  Modify the event loop to recognize the new type of event.
  20071.  
  20072. 4.  Inform the Operating System that your application can receive and act on the
  20073.     required AppleEvents.
  20074.  
  20075. The following four sections provide further details on each of these steps. For
  20076. a more complete story, see the Event Manager chapter in this volume.
  20077.  
  20078. _______________________________________________________________________________
  20079.  
  20080. æKY Selecting…AppleEvents…to…Support
  20081. æC »Selecting AppleEvents to Support                              Compatibility Guidelines
  20082. _______________________________________________________________________________
  20083.  
  20084. First you need to identify the AppleEvents that you want your application to
  20085. support. To make your application 7.0-friendly, you need to support the required
  20086. AppleEvents that Apple Computer, Inc. has already defined. Table 3-1 lists the
  20087. required AppleEvents, together with the parameters passed to the application
  20088. with each kind of AppleEvent.
  20089.  
  20090. Table 3-1.  Required AppleEvents
  20091.  
  20092. Event               Parameters           Description
  20093. Open Application    none                 open an application
  20094. Open Documents      list of documents    open each specified document
  20095. Print               list of documents    print each specified document
  20096. Quit                none                 terminate and exit the application
  20097. Setup               none                 update application’s menu items
  20098. Get                 property             return value of specified property
  20099.  
  20100. Your application should already contain code to accomplish these standard
  20101. operations. If so, you may still need to modify that code as described in the
  20102. next section.
  20103. _______________________________________________________________________________
  20104.  
  20105. æKY Isolating…User…Interface…Code
  20106. æC »Isolating User Interface Code                                 Compatibility Guidelines
  20107. _______________________________________________________________________________
  20108.  
  20109. You need to separate code that interacts with users from code that actually
  20110. performs the operations requested by the required AppleEvents. Generally, it is
  20111. easy to mix user interface code with code that performs some operation, so you
  20112. need to think carefully about this step. For example, many print loops have a
  20113. section that begins like this:
  20114.  
  20115. IF ( PrStlDialog(thePrRecHdl) ) THEN BEGIN
  20116.   IF ( PrJobDialog(thePrRecHdl) ) THEN BEGIN
  20117.     thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);
  20118.     IF ( PrError = noErr ) THEN BEGIN
  20119.       PrOpenPage(thePrPort, NIL);
  20120.  
  20121. Similarly, this fragment might execute when a user chooses Open from the File
  20122. menu:
  20123.  
  20124. IF SFGetFile(pt, str, fileFilter, numTypes,
  20125.      typeList, dlgHook, reply) THEN BEGIN
  20126.   err := FSOpen(reply.fName, reply.vRefNum, refNum);
  20127.  
  20128. Since an AppleEvent (and not the user) might instruct your application to open
  20129. or print a document, the application needs to be able to perform the requested
  20130. operation without displaying the print or file dialog boxes. A way to do this in
  20131. version 7.0 might go like this:
  20132.  
  20133. FUNCTION PresentPrintDialogs: Boolean;
  20134. VAR
  20135.   thePrRecHandle: THPrint;
  20136. BEGIN
  20137.   PresentPrintDialogs := FALSE;
  20138.   IF ( PrStlDialog(thePrRecHdl) ) THEN
  20139.     IF ( PrJobDialog(thePrRecHdl) ) THEN
  20140.       PresentPrintDialogs := TRUE;
  20141. END;
  20142.  
  20143. PROCEDURE PrintDocument(thePrRecHdl: THPrint);
  20144. VAR
  20145.   thePrPort:  TPPrPort;
  20146. BEGIN
  20147.   thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);
  20148.   IF ( PrError = noErr ) THEN BEGIN
  20149.     PrOpenPage(thePrPort,NIL);
  20150.   ...
  20151.   END;
  20152. END;
  20153.  
  20154. In this way, your application can respond to print requests both from the user
  20155. and from any AppleEvents it receives.
  20156.  
  20157. _______________________________________________________________________________
  20158.  
  20159. æKY Modifying…the…Event…Loop
  20160. æC »Modifying the Event Loop                                      Compatibility Guidelines
  20161. _______________________________________________________________________________
  20162.  
  20163. In system software version 7.0, the Event Manager manages three classes of
  20164. events: low-level events (which are the traditional user-initiated events like
  20165. mouse and keyboard events), operating system event (which inform applications of
  20166. changes in their operating status), and high-level event (which include
  20167. AppleEvents). AppleEvents are reported to an application using a new event type
  20168. defined by the constant kHighLevelEvent.
  20169.  
  20170. CONST  kHighLevelEvent  = 23;
  20171.  
  20172. This means that you need to add a new selector to your branch statements.
  20173. Listing 3-2 shows a simple event loop modified to accept AppleEvents.
  20174.  
  20175. Listing 3-2.  An event loop modified to receive high-level events
  20176.  
  20177. PROCEDURE DoEvent(event: EventRecord);
  20178. BEGIN
  20179.   CASE event.what OF
  20180.     nullEvent:
  20181.       DoIdle;
  20182.     mouseDown:
  20183.       DoMouseDown(event);
  20184.     mouseUp:
  20185.       DoMouseUp(event);
  20186.     keyDown, autoKey: 
  20187.       DoKeyDown(event);
  20188.     activateEvt:
  20189.       DoActivate(event);
  20190.     updateEvt:
  20191.       DoUpdate(event);
  20192.     kOSEvent:
  20193.       DoOSEvent(event);
  20194.     kHighLevelEvent:
  20195.       DoHighLevelEvent(event);
  20196.   END;
  20197. END; {DoEvent}
  20198.  
  20199. At this point, you need to provide the DoHighLevelEvent routine to handle the
  20200. AppleEvent (or other high-level event). Once you’ve separated the relevant
  20201. user-interface part of your code, modified your event loop, and added a
  20202. procedure that accepts high-level events, all you need to do is write a bit of
  20203. code that knows how to look at AppleEvents and then calls the correct operation.
  20204.  
  20205. _______________________________________________________________________________
  20206.  
  20207. æKY Indicating…an…Application…Is…AppleEvent-Aware
  20208. æC »Indicating an Application Is AppleEvent-Aware                 Compatibility Guidelines
  20209. _______________________________________________________________________________
  20210.  
  20211. The final thing you need to do is inform the Operating System that your
  20212. application is able to receive and process AppleEvents. To accomplish this, you
  20213. need to modify your application’s 'SIZE' resource, as explained in the Event
  20214. Manager chapter.
  20215.  
  20216. _______________________________________________________________________________
  20217.  
  20218. æKY Removing…Font…Size…Restrictions
  20219. æC »Removing Font Size Restrictions                               Compatibility Guidelines
  20220. _______________________________________________________________________________
  20221.  
  20222. System software version 7.0 introduces outline fonts, known as TrueType™. An
  20223. outline font can be printed or displayed at any point size without the jagged
  20224. appearance of some bitmapped fonts. A 7.0-friendly application should allow its
  20225. users to take advantage of this improvement. Minimally, this means that users
  20226. should be able to ask for any point size up to 32,768. Many applications now let
  20227. users specify font sizes up to 127 point, but you should remove even this
  20228. limitation when running in version 7.0. In addition, your application should
  20229. allow users to increment or decrement the font size by 1 point.
  20230.  
  20231. You can use the IsOutline routine, documented in the Font Manager chapter in
  20232. this volume, to see if a particular font is an outline font. If it is, you might
  20233. wish to indicate that fact in your font size menu. For example, suppose that
  20234. your Size menu for a particular bitmapped font looks like the one in Figure 3-1.
  20235.  
  20236. ø 3.1  Size menu for a bitmapped font
  20237.  
  20238. To provide a visual indication that the selected font is an outline font that
  20239. looks good at any size, you might change the menu to look like the one in Figure
  20240. 3-2. One way to do this is by outlining all available sizes, as well as the
  20241. Other item.
  20242.  
  20243. ø 3.2  Size menu for an outline font
  20244.  
  20245. The User Interface Guidelines chapter contains additional suggestions on
  20246. incorporating outline fonts into your application.
  20247.  
  20248. _______________________________________________________________________________
  20249.  
  20250. æKY Operating…With…Virtual…Memory
  20251. æC »Operating With Virtual Memory                                 Compatibility Guidelines
  20252. _______________________________________________________________________________
  20253.  
  20254. System software version 7.0 supports virtual memory, a memory management scheme
  20255. that extends the logical address space of the machine by using part of the
  20256. available secondary storage (usually, a hard disk) to store parts of memory that
  20257. are not currently in use. When virtual memory is present, the perceived amount
  20258. of RAM can extend up to 14 megabytes on systems with 24-bit ROMs and up to 4
  20259. gigabytes on systems with 32-bit clean ROMs. Since the Operating System has more
  20260. addressable memory, your applications can ask for and receive larger blocks of
  20261. memory than they would if virtual memory were not available.
  20262.  
  20263. Virtual memory is available only on machines equipped with a memory management
  20264. unit (MMU). Currently, these machines include 68030-based machines (where the
  20265. MMU is built into the CPU) as well as 68020-based machines that contain the
  20266. 68851 Paged Memory Management Unit. You can use the Gestalt function to
  20267. determine whether virtual memory is installed. If it is, you may need to
  20268. exercise caution to ensure that the normally invisible operation of virtual
  20269. memory does not adversely affect the execution of your application. Applications
  20270. that might need to be concerned with virtual memory include those that have
  20271. critical timing requirements, execute code at interrupt time, or perform
  20272. debugging operations.
  20273.  
  20274. Note:  The vast majority of applications do not need to know whether virtual
  20275. memory is installed.  
  20276.  
  20277. One type of application that might need to know if virtual memory is operating
  20278. is a multimedia application that manages very large images or incorporates many
  20279. sounds into its presentations. Imagine that such an application wants to display
  20280. a large number of intricate color images in rapid succession, and that some of
  20281. those images are as large as a megabyte each. If virtual memory is operating, it
  20282. is very likely that parts of those images are on disk when they need to be
  20283. displayed. This means that in the middle of drawing a picture, the system has to
  20284. stop long enough to read those parts of the picture off the disk. The result is
  20285. that a noticeable delay may occur, which may be unacceptable.
  20286.  
  20287. In a case like this, you can use routines that lock the appropriate data into
  20288. RAM, so that displaying the image requires no disk access. These routines are
  20289. fully documented in the Memory Management chapter later in this volume. Other
  20290. software that may need to know about those routines includes drivers, interrupt
  20291. code, and debugging applications.
  20292.  
  20293. _______________________________________________________________________________
  20294.  
  20295. æKY Localizing…Macintosh…Programs
  20296. æC »LOCALIZING MACINTOSH PROGRAMS                                 Compatibility Guidelines
  20297. _______________________________________________________________________________
  20298.  
  20299. Localization is the process of adapting an application to a specific language
  20300. and country. By planning ahead and making localization relatively painless, 
  20301. you’ll ensure that international markets are available for your product in the
  20302. future. This section provides a brief overview of what you need to do to make it
  20303. easy to localize your application. For the complete account of writing software
  20304. that is compatible with Macintosh computers throughout the world, you should
  20305. read the TextEdit chapter and the Worldwide Software Overview later in this
  20306. volume. You should also consult the “Developing Worldwide Software” section in
  20307. the User Interface Guidelines chapter of this volume.
  20308.  
  20309. _______________________________________________________________________________
  20310.  
  20311. æKY General…Guidelines…for…Compatibility
  20312. æC »General Guidelines                                            Compatibility Guidelines
  20313. _______________________________________________________________________________
  20314.  
  20315. The key to easy localization is to store country-dependent information used by
  20316. your application as resources (rather than within the application’s code). Text
  20317. seen by the user can then be translated without modifying the code. In addition,
  20318. storing such information in resources means that your application can be adapted
  20319. for a different country simply by substituting the appropriate resources. Make
  20320. sure that at least the following kinds of information are stored in resources:
  20321.  
  20322.   •   all text, including special characters and delimiters
  20323.  
  20324.   •   menus and keyboard equivalents for menu commands (if available)
  20325.  
  20326.   •   character, word, phrase, and text translation tables
  20327.  
  20328.   •   address formats, including zip codes and phone numbers
  20329.  
  20330. When you create resources for your applications, remember the following key
  20331. points:
  20332.  
  20333.   •   text needs room to grow (up, down, and sideways)
  20334.  
  20335.   •   translated text is often 50 percent larger than the U.S. English text
  20336.  
  20337.   •   diacritical marks, widely used outside the United States, may extend up
  20338.       to the ascent line
  20339.  
  20340.   •   some system fonts contain characters that extend to both the ascent and
  20341.       descent lines
  20342.  
  20343.   •   potential grammar problems may arise from error messages, “natural”
  20344.       programming language structures, and so forth
  20345.  
  20346.   •   text location within a window should be easy to change
  20347. _______________________________________________________________________________
  20348.  
  20349. æKY Other…Localization…Tools
  20350. æC »Other Localization Tools                                      Compatibility Guidelines
  20351. _______________________________________________________________________________
  20352.  
  20353. In addition to these general guidelines, you need to be aware of a host of other
  20354. localization issues, such as differences in script systems and measurement
  20355. systems. System software version 7.0 contains updated versions of several tools
  20356. that you can use to facilitate localization of your applications—TextEdit, the
  20357. International Utilities Package, and the Script Manager.
  20358.  
  20359. Perhaps the most important localization tool is the Script Manager, which
  20360. contains routines that allow your application to function correctly with
  20361. non-Roman scripts (or writing systems). The Script Manager furnishes a standard
  20362. interface that allows installation of different script systems, maintains global
  20363. data structures, supports switching keyboards between different scripts, and
  20364. provides a central dispatcher that gives your application access to script
  20365. systems. It also contains utilities for text processing and parsing, which are
  20366. useful for applications that do a lot of text manipulation. The Script Manager
  20367. provides easy ways to translate your application into another writing system and
  20368. to coordinate with the International Utilities Package.
  20369.  
  20370. The International Utilities Package provides routines for dealing with sorting,
  20371. currency, measurement systems, and date and time formatting. These tend to vary
  20372. in some degree from script to script, language to language, and country to
  20373. country, and your application should take advantage of the Macintosh Operating
  20374. System’s ability to present this information in the correct format. It is
  20375. important that you use the routines in this package rather than the System
  20376. Utility routines contained in ROM; the ROM routines are not as accurate and 
  20377. (because they are used by the File Manager) cannot be localized for different
  20378. countries.
  20379.  
  20380. TextEdit provides routines that handle basic text formatting and editing
  20381. capabilities, such as inserting new text or scrolling text within a window. The
  20382. version of TextEdit included in system software version 7.0 contains new
  20383. features that allow it to work with different scripts. For example, TextEdit 3.0
  20384. takes advantage of the Script Manager’s handling of double-byte characters to
  20385. display scripts (such as Kanji) with improved accuracy and consistency.
  20386.  
  20387. For more information about the enhanced versions of TextEdit, see the TextEdit
  20388. chapter in this volume. For complete information on both the International
  20389. Utilities Package and the Script Manager, see the Worldwide Software Overview
  20390. chapter.
  20391.  
  20392. _______________________________________________________________________________
  20393.  
  20394. æKY Running…Macintosh…Programs…Under…A/UX
  20395. æC »RUNNING MACINTOSH PROGRAMS UNDER A/UX                         Compatibility Guidelines
  20396. _______________________________________________________________________________
  20397.  
  20398. A/UX is Apple’s version of the UNIX operating system, which provides a
  20399. multitasking and multiuser software execution environment. One of the most
  20400. distinctive features of A/UX in comparison with other implementations of the
  20401. UNIX operating system is its ability to run conforming Macintosh applications.
  20402. Within limits described later in this section, applications developed for the
  20403. Macintosh Operating System using the standard Macintosh User Interface Toolbox
  20404. routines will execute under A/UX. Figure 3-3 shows a typical screen under A/UX.
  20405.  
  20406. ø 3.3  The Macintosh User Interface Under A/UX
  20407.  
  20408. The ability to run Macintosh applications under A/UX is provided by enhancements
  20409. to the A/UX kernel and by a library of functions known as the A/UX Toolbox. The
  20410. A/UX Toolbox is a library of routines that enables a program running under A/UX
  20411. to call Macintosh Toolbox routines and native Macintosh Operating System
  20412. routines. The A/UX Toolbox provides a bridge between the Macintosh and A/UX
  20413. environments, giving you two kinds of code compatibility:
  20414.  
  20415.   •   You can execute Macintosh binary code (applications compiled in the
  20416.       Macintosh environment) under A/UX, within the current limitations of the
  20417.       A/UX Toolbox.
  20418.  
  20419.   •   You can write common source code that can be separately built (that is,
  20420.       compiled and linked) into executable code for both environments.
  20421.  
  20422. The A/UX Toolbox operates transparently to the user and to the application
  20423. developer. This means that (subject once again to qualifications detailed later)
  20424. your applications developed for the Macintosh Operating System should execute
  20425. under the A/UX operating system.
  20426.  
  20427. The version of A/UX currently available is A/UX Release 2.0, which greatly
  20428. extends the capabilities of earlier versions. Release 2.0 supports more managers
  20429. and drivers than previous versions, thereby increasing the level of
  20430. compatibility with Macintosh applications. There is now transparent access to
  20431. Macintosh file systems from within A/UX, so users no longer have to transfer
  20432. files between the two systems manually.
  20433.  
  20434. This section briefly explains how the A/UX Toolbox works and then provides
  20435. details on writing Macintosh applications that execute under the A/UX operating
  20436. system. A/UX Release 2.0 provides such a high level of compatibility with
  20437. Macintosh applications that your existing applications may very well run under 
  20438. A/UX with no changes whatsoever. To run successfully under A/UX Release 2.0,
  20439. your application should
  20440.  
  20441.   •   be compatible with MultiFinder
  20442.  
  20443.   •   be 32-bit clean (that is, operate in an environment where all 32 bits of
  20444.       a handle or pointer are significant in determining memory addresses)
  20445.  
  20446.   •   use the Gestalt Manager to determine whether the appropriate versions of
  20447.       managers are present in the current operating environment
  20448.  
  20449.   •   avoid reading or writing low-memory global variables
  20450.  
  20451. In general, applications that conform to the interfaces documented in Inside
  20452. Macintosh, are MultiFinder-aware, do not rely on low-memory global variables,
  20453. and heed the various guidelines presented in “About Compatibility” should
  20454. operate under A/UX.
  20455.  
  20456. _______________________________________________________________________________
  20457.  
  20458. æKY How…the…A/UX…Toolbox…Works
  20459. æC »How the A/UX Toolbox Works                                    Compatibility Guidelines
  20460. _______________________________________________________________________________
  20461.  
  20462. The primary function of the A/UX Toolbox is to make available to programs
  20463. running under A/UX the standard Macintosh support code described in Inside
  20464. Macintosh. Most of the support code consists of routines built into the
  20465. Macintosh ROM.
  20466.  
  20467. The ROM routines fall into two categories, User Interface Toolbox routines and
  20468. Macintosh Operating System routines. The A/UX Toolbox uses one of two strategies
  20469. for supporting a Macintosh ROM call, depending on whether the call is to the
  20470. User Interface Toolbox or to the native Macintosh Operating System.
  20471.  
  20472. When an A/UX Toolbox application calls one of the Macintosh User Interface
  20473. Toolbox routines, the A/UX Toolbox intercepts the call and, if necessary,
  20474. translates the parameters into a form usable by the ROM. After the A/UX Toolbox
  20475. performs the translation, it invokes the ROM code that would be used in the
  20476. native Macintosh environment.
  20477.  
  20478. When an A/UX Toolbox application calls one of the Macintosh Operating System
  20479. routines, the A/UX Toolbox diverts the call to a substitute routine in its own
  20480. library. The A/UX Toolbox Operating System routines call the standard A/UX
  20481. libraries to perform the A/UX equivalents of the Macintosh Operating System
  20482. functions. The Macintosh Operating System ROM code is never used under A/UX.
  20483. Note that some of the built-in User Interface Toolbox routines generate calls to
  20484. the Macintosh Operating System routines; these calls are also intercepted by the
  20485. A/UX Toolbox and diverted to routines in its own library.
  20486.  
  20487. Figure 3-4 illustrates how the two elements of the A/UX Toolbox library interact
  20488. with the application and the ROM code.
  20489.  
  20490. ø 3.4  Interactions among applications, the A/UX Toolbox, and ROM code
  20491.  
  20492. _______________________________________________________________________________
  20493.  
  20494. æKY Using…the…A/UX…Toolbox
  20495. æC »Using the A/UX Toolbox                                        Compatibility Guidelines
  20496. _______________________________________________________________________________
  20497.  
  20498. The primary limitation on Macintosh applications running under A/UX is that the
  20499. A/UX Toolbox does not currently support all managers and drivers. Table 3-2
  20500. summarizes the status of various ROM libraries in A/UX Release 2.0.
  20501.  
  20502. Table 3-2.  Status of User Interface Toolbox and Macintosh Operating System
  20503. libraries in the A/UX Toolbox 
  20504.  
  20505. ROM Library                               Implementation
  20506.  
  20507. Alias Manager                             None
  20508. Apple Desktop Bus                         None
  20509. Binary-Decimal Conversion Package         Full
  20510. Color Manager                             Full
  20511. Color Picker Package                      Full
  20512. Color QuickDraw                           Full
  20513. Control Manager                           Full
  20514. Database Access Manager                   None
  20515. Deferred Task Manager                     None
  20516. Desk Manager                              Full
  20517. Device Manager                            Full
  20518. Dialog Manager                            Full
  20519. Disk Driver                               Full
  20520. Disk Initialization Package               Full
  20521. Edition Manager                           None
  20522. Event Manager, Operating System           Partial
  20523. Event Manager, Toolbox                    Full*
  20524. File Manager                              Full
  20525. Floating Point Arithmetic                
  20526.   and Transcendental Functions Packages   Full*
  20527. Font Manager                              Full
  20528. Gestalt Manager                           Full
  20529. Help Manager                              None
  20530. International Utilities Package           Full
  20531. List Manager Package                      Full
  20532. Memory Manager                            Full
  20533. Menu Manager                              Full
  20534. Notification Manager                      Full
  20535. Package Manager                           Full
  20536. Palette Manager                           Full
  20537. Power Manager                             None
  20538. PPC Toolbox                               None
  20539. Printing Manager                          Full
  20540. QuickDraw                                 Full
  20541. Resource Manager                          Full
  20542. Scrap Manager                             Full
  20543. Script Manager                            Full
  20544. SCSI Manager                              None
  20545. Segment Loader                            Partial
  20546. Serial Driver                             Full
  20547. Shutdown Manager                          Full*
  20548. Slot Manager                              Full
  20549. Sound Manager                             Full
  20550. Startup Manager                           Full
  20551. Standard File Package                     Full
  20552. System Error Handler                      Full*
  20553. TextEdit                                  Full
  20554. Time Manager                              Full*
  20555. Utilities, Operating System               Partial
  20556. Utilities, Toolbox                        Full
  20557. Vertical Retrace Manager                  Partial
  20558. Window Manager                            Full
  20559.  
  20560. Note that when A/UX Release 2.0 implements a particular manager or driver, the
  20561. version of that manager or driver may not be the same as the version available
  20562. in the Macintosh Operating System. This means that, whenever possible, you
  20563. should use Gestalt to check for the existence of the particular features your
  20564. application needs. In managers or drivers marked with an asterisk (*), all calls
  20565. are implemented under A/UX, but the behavior is not identical to that in the
  20566. Macintosh Operating System. See the publication A/UX Toolbox: Macintosh ROM
  20567. Interface for complete details on the implementation of these managers and
  20568. drivers.
  20569.  
  20570. _______________________________________________________________________________
  20571.  
  20572. æKY A/UX…Compatibility…Guidelines
  20573. æC »A/UX Compatibility Guidelines                                 Compatibility Guidelines
  20574. _______________________________________________________________________________
  20575.  
  20576. The A/UX Toolbox has been designed to allow as many Macintosh applications as
  20577. possible to execute under the A/UX operating system. Because of profound
  20578. differences between the two environments, however, it is possible that some
  20579. applications may not execute correctly under A/UX. By following these
  20580. guidelines, you can help ensure that your Macintosh applications run under A/UX.
  20581.  
  20582.   •   Make certain that your application is MultiFinder-friendly. MultiFinder
  20583.       is a standard part of A/UX Release 2.0, just as it is in system software
  20584.       version 7.0. Your application should include a 'SIZE' resource and call
  20585.       WaitNextEvent in its main event loop. Note that the version of
  20586.       MultiFinder included with A/UX Release 2.0 is functionally equivalent to
  20587.       the version of MultiFinder released with system software version 6.0.5,
  20588.       but has been customized for use under A/UX.
  20589.  
  20590.   •   Always use the available managers and drivers to manipulate hardware
  20591.       devices. In the Macintosh Operating System, individual processes and the
  20592.       various libraries can have much more control over the system than under
  20593.       A/UX, where the kernel manages all interaction between processes and the
  20594.       underlying hardware. In particular, do not attempt to read data from or
  20595.       write data to any of the memory-mapped hardware available on a Macintosh
  20596.       computer.
  20597.  
  20598.   •   Avoid relying on any of the low-memory global variables. Not all of them
  20599.       are available under A/UX.
  20600.  
  20601.   •   Make certain that your application is 32-bit clean (that is, it operates
  20602.       in an environment where all 32 bits of a handle or pointer are
  20603.       significant in determining memory addresses).
  20604.  
  20605.   •   Use the Gestalt Manager to determine which versions of managers and
  20606.       drivers are present in the current operating environment before relying
  20607.       on features that are not common to all released versions. Generally, the
  20608.       versions of managers available under A/UX Release 2.0 are the same as
  20609.       those versions included in Macintosh system software version 6.0.5.
  20610.  
  20611. Finally, your application should conform to the programming interfaces described
  20612. in Inside Macintosh and should follow the basic compatibility guidelines
  20613. presented in “About Compatibility” earlier in this chapter.
  20614.  
  20615. _______________________________________________________________________________
  20616.  
  20617. æKY About…the…Gestalt…Manager
  20618. æC »ABOUT THE GESTALT MANAGER                                     Compatibility Guidelines
  20619. _______________________________________________________________________________
  20620.  
  20621. The Macintosh family of computers has grown tremendously in the past several
  20622. years, and it is likely to grow in the future. Macintosh software now runs on a
  20623. number of different processors, some of which are accompanied by floating-point
  20624. coprocessors or memory management units. In addition, the installed versions of
  20625. the system software, drivers, and QuickDraw routines may vary from machine to
  20626. machine. To ensure that your applications are maximally compatible with existing
  20627. and future versions of the Macintosh, you should keep references to specific
  20628. software and hardware features to a minimum. In general, applications should
  20629. communicate with the system software and hardware through the available managers
  20630. and device drivers. If, however, it is necessary or useful for your applications
  20631. to take advantage of software or hardware components that may not be present on
  20632. all Macintosh computers, then you need some method of determining whether those
  20633. components are available. The Gestalt Manager serves this need by allowing you
  20634. to get information about the operating environment in a simple and efficient
  20635. manner.
  20636.  
  20637. System software version 7.0 is a major software release that affects the entire
  20638. Macintosh line of computers, spanning different CPUs, different versions of ROM,
  20639. and machines with a variety of hardware and software configurations. Version 7.0
  20640. introduces several new managers and makes significant changes to many existing
  20641. managers. To take advantage of new version 7.0 features, and to run on as many
  20642. machines as possible, it is more important than ever before to determine the
  20643. software and hardware components available in a particular operating
  20644. environment.
  20645.  
  20646. To deal with this increasingly complex situation, system software version 7.0
  20647. includes the Gestalt Manager. This manager includes the Gestalt function, which
  20648. is a replacement for both the SysEnvirons function and the Environs procedure.
  20649. The Gestalt function gives applications the ability to determine information
  20650. about a large number of machine-dependent features. You can use the Gestalt
  20651. function to find the following sorts of information about the hardware
  20652. configuration and operating environment of the machine your application is
  20653. executing on:
  20654.  
  20655.   •   the type of machine
  20656.   •   the version of the System file currently running
  20657.   •   the type of CPU
  20658.   •   the type of keyboard attached to the machine
  20659.   •   the type of floating-point processing unit (FPU), if any
  20660.   •   the type of memory management unit (MMU), if any
  20661.   •   the size of available RAM
  20662.   •   the amount of available virtual memory
  20663.   •   the versions of various drivers and managers
  20664.   •   the features of various drivers and managers
  20665.   •   the version of QuickDraw currently present
  20666.   •   whether the A/UX operating system is running or not
  20667.  
  20668. How your application uses the resulting information depends on what your
  20669. application needs to accomplish. For example, in a case where critical hardware
  20670. features are not available, your application might display an alert box to
  20671. notify the user that the required hardware is missing and then terminate. Or, if
  20672. your application has determined that Color QuickDraw is available, it could
  20673. execute alternate code to take advantage of the expanded capabilities of that
  20674. software.
  20675.  
  20676. Associated with the Gestalt function are two other functions—one that allows an
  20677. application to register new features with Gestalt and another that allows an
  20678. application to change the function used by Gestalt to retrieve a particular
  20679. piece of information. These two functions make it easy for your application to
  20680. announce its presence to other applications, in case they wish to alter their
  20681. actions in view of the presence of your application. For example, a macro
  20682. utility that intercepts sequences of keyboard presses and translates them into
  20683. other sequences can register itself with Gestalt at system initialization time;
  20684. afterward, other applications can call Gestalt to determine if that utility is
  20685. present. In this way, Gestalt can act as a central clearinghouse for information
  20686. on the available hardware and software features of the operating environment,
  20687. including any third-party applications that register themselves with Gestalt.
  20688. Gestalt therefore provides a further means of cooperation and awareness among
  20689. applications executing in the version 7.0 environment.
  20690.  
  20691. Although the Gestalt function can provide your application with most of the
  20692. basic information it needs about particular software or hardware features, you
  20693. may still need to call other routines to determine more specific features. For
  20694. example, if you need to determine the resolution of the Macintosh screen, you
  20695. can use the Toolbox Utility procedure ScreenRes. (See the Toolbox Utilities
  20696. chapter of Inside Macintosh, Volume I, for a description of this procedure.)
  20697. The Gestalt function replaces both the Environs procedure and the current
  20698. implementation of the SysEnvirons function as the standard means of determining
  20699. specific aspects of the operating environment. The Gestalt Manager is simpler to
  20700. use and provides more information than either of those routines. Applications
  20701. that use SysEnvirons still execute correctly in system software version 7.0 (the
  20702. SysEnvirons function calls the Gestalt function).
  20703.  
  20704. Use of the Environs procedure is no longer recommended, because it encourages
  20705. you to think in terms of ROM versions, not in term of features that may be
  20706. available. The Gestalt Manager can also provide information such as ROM version
  20707. and size, but you should not write applications that infer the presence of
  20708. particular software or hardware features on the basis of that information. When
  20709. you need to know whether a particular feature is present, you should request
  20710. information about it directly, using the appropriate Gestalt selector.
  20711.  
  20712. Although you can still call the SysEnvirons function, the Gestalt Manager is
  20713. simpler and more efficient, and is the recommended way to get information about
  20714. the operating environment. SysEnvirons returns a pointer to a system environment
  20715. record containing nine different pieces of information. Gestalt returns only the
  20716. information requested by use of a specific selector code parameter. In most
  20717. cases, your application really needs only a part of what is contained in the
  20718. system environment record. With Gestalt, your application can request only the
  20719. information it needs.
  20720.  
  20721. _______________________________________________________________________________
  20722.  
  20723. æKY Using…the…Gestalt…Manager
  20724. æC »USING THE GESTALT MANAGER                                     Compatibility Guidelines
  20725. _______________________________________________________________________________
  20726.  
  20727. The Gestalt Manager includes three functions—Gestalt, NewGestalt, and
  20728. ReplaceGestalt. You can use the Gestalt function to obtain information about
  20729. software or hardware components available on the current machine. You can use
  20730. NewGestalt to register new software modules (such as drivers and patches) with
  20731. the Operating System. Use ReplaceGestalt to replace the function associated with
  20732. a particular selector code by some other function.
  20733.  
  20734. Note:  Most applications do not need to use either NewGestalt or ReplaceGestalt.
  20735.  
  20736. _______________________________________________________________________________
  20737.  
  20738. æKY Determining…Features…of…the…Operating…Environment
  20739. æC »Determining Features of the Operating Environment             Compatibility Guidelines
  20740. _______________________________________________________________________________
  20741.  
  20742. When your application needs information about a specific software or hardware
  20743. feature that can be provided by the Gestalt function, your application can pass
  20744. Gestalt a selector code (or selector) as one of the parameters. The selector
  20745. code is simply an indication of what information your application currently
  20746. needs. There are two types of selector codes—predefined selector codes that are
  20747. always recognized by Gestalt, and application-defined selector codes that
  20748. applications may register with Gestalt by calling the NewGestalt function.
  20749.  
  20750. If Gestalt can determine the requested information, it returns that information
  20751. in its second parameter, known as the response parameter. If Gestalt cannot
  20752. obtain the desired information, it returns a result code indicating the cause of
  20753. the error, and the value of the response parameter is undefined. You should
  20754. always check the result code returned by Gestalt to make sure that the response
  20755. parameter contains meaningful information.
  20756.  
  20757. Note:  When passed one of the predefined selector codes, Gestalt does not move
  20758. or purge memory and therefore may be called at any time, even at interrupt time.
  20759. However, selector functions associated with application-defined selector codes
  20760. may move or purge memory, and applications can alter Gestalt’s predefined
  20761. selector functions. As a result, it is safest to assume that Gestalt might
  20762. always move or purge memory. The NewGestalt function may move memory and should
  20763. not be called at interrupt time.
  20764.  
  20765. There are two types of predefined selector codes: codes that return information
  20766. that your application can use to guide its actions (known as environmental
  20767. selectors), and codes that provide information only and should never be used as
  20768. an indication of some feature’s existence (known as informational selectors).
  20769.  
  20770. It is particularly important that you understand the difference between
  20771. environmental and informational selectors. The response returned by Gestalt when
  20772. it is passed an informational selector is for your (or the user’s) edification
  20773. only and should never be used by your application as a means of determining
  20774. whether some specific software or hardware feature is available. For example,
  20775. you can use Gestalt to determine the version of the ROM installed on a
  20776. particular machine, but you should never use this information to guide any of
  20777. your application’s actions. Routines you expect to be in ROM may actually be in
  20778. RAM; hence, you cannot determine that some routine usually found in ROM is not
  20779. present simply by looking at the ROM version. Also, routines contained in ROM
  20780. may have been patched by the system at startup time, in which case the system
  20781. might not have the features that you think it has on the basis of the reported
  20782. ROM version. Similar remarks apply to other informational selectors such as ROM
  20783. size, machine type, and System file version.
  20784.  
  20785. You can use the following environmental selectors to determine information about
  20786. the operating environment.
  20787.  
  20788. CONST
  20789. gestaltVersion                = 'vers';  {Gestalt version}
  20790. gestaltAddressingModeAttr     = 'addr';  {addressing mode attributes}
  20791. gestaltAliasMgrAttr           = 'alis';  {Alias Mgr attributes}
  20792. gestaltAppleTalkVersion       = 'atlk';  {AppleTalk version}
  20793. gestaltAUXVersion             = 'a/ux';  {A/UX version if present}
  20794. gestaltCTBVersion             = 'ctbv';  {Comm Toolbox version}
  20795. gestaltDBAccessMgrAttr        = 'dbac';  {Database Access Mgr attrs}
  20796. gestaltEditionMgrAttr         = 'edtn';  {Edition Mgr attributes}
  20797. gestaltAppleEventsAttr        = 'evnt';  {AppleEvents attributes}
  20798. gestaltFolderMgrAttr          = 'fold';  {Folder Mgr attributes}
  20799. gestaltFontMgrAttr            = 'font';  {Font Mgr attributes}
  20800. gestaltFPUType                = 'fpu ';  {FPU type}
  20801. gestaltHardwareAttr           = 'hdwr';  {hardware attributes}
  20802. gestaltHelpMgrAttr            = 'help';  {Help Mgr attributes}
  20803. gestaltKeyboardType           = 'kbd ';  {keyboard type}
  20804. gestaltLowMemorySize          = 'lmem';  {low-memory area size}
  20805. gestaltLogicalRAMSize         = 'lram';  {logical RAM size}
  20806. gestaltMiscAttr               = 'misc';  {miscellaneous attributes}
  20807. gestaltMMUType                = 'mmu ';  {MMU type}
  20808. gestaltNotificationMgrAttr    = 'nmgr';  {Notification Mgr attrs}
  20809. gestaltOSAttr                 = 'os  ';  {O/S attributes}
  20810. gestaltLogicalPageSize        = 'pgsz';  {logical page size}
  20811. gestaltPPCToolboxAttr         = 'ppc ';  {PPC Toolbox attributes}
  20812. gestaltPowerMgrAttr           = 'powr';  {Power Mgr attributes}
  20813. gestaltProcessorType          = 'proc';  {processor type}
  20814. gestaltParityAttr             = 'prty';  {parity attributes}
  20815. gestaltQuickdrawVersion       = 'qd  ';  {QuickDraw version}
  20816. gestaltPhysicalRAMSize        = 'ram ';  {physical RAM size}
  20817. gestaltResourceMgrAttr        = 'rsrc';  {Resource Mgr attributes}
  20818. gestaltScriptMgrVersion       = 'scri';  {Script Mgr version}
  20819. gestaltScriptCount            = 'scr#';  {# of active script systems}
  20820. gestaltSoundAttr              = 'snd ';  {sound attributes}
  20821. gestaltTextEditVersion        = 'te  ';  {TextEdit version}
  20822. gestaltTimeMgrVersion         = 'tmgr';  {Time Mgr version}
  20823. gestaltVMAttr                 = 'vm  ';  {virtual memory attributes}
  20824.  
  20825. The following informational selectors are provided for informational purposes
  20826. only. You can display the information returned when using these selectors, but
  20827. you should never use this information as an indication of what software features
  20828. or hardware may be available.
  20829.  
  20830. CONST
  20831. gestaltMachineType            = 'mach';  {machine type}
  20832. gestaltROMSize                = 'rom ';  {ROM size}
  20833. gestaltROMVersion             = 'romv';  {ROM version}
  20834. gestaltSystemVersion          = 'sysv';  {System file version}
  20835.  
  20836. “Interpreting Gestalt Responses” later in this chapter provides the exact
  20837. meaning of each of these selectors and of the values returned by Gestalt in each
  20838. case.
  20839.  
  20840. _______________________________________________________________________________
  20841.  
  20842. æKY Determining…Whether…Gestalt…Is…Available
  20843. æC »Determining Whether Gestalt Is Available                      Compatibility Guidelines
  20844. _______________________________________________________________________________
  20845.  
  20846. Because the Gestalt Manager currently exists only in system software versions
  20847. 6.0.4 and later (and in ROM on the Macintosh IIci and Portable), you should make
  20848. certain that it is actually available before attempting to call it. You can do
  20849. this by using the TrapAvailable function defined above in “Determining Whether a
  20850. Trap Is Available.” Listing 3-3 uses that function to determine whether the
  20851. Gestalt Manager is available.
  20852.  
  20853. Note:  If you are using the MPW development system version 3.2 or later, then
  20854. you do not need to perform this check, because that system provides glue
  20855. routines that allow you to call Gestalt even if it is not in ROM or in the
  20856. System file. However, if you are programming in assembly language, this glue is
  20857. not provided (and you still need to check that Gestalt is available before
  20858. calling it).  
  20859.  
  20860. Listing 3-3.  Determining whether Gestalt is available
  20861.  
  20862. FUNCTION GestaltAvailable: Boolean;
  20863. CONST
  20864.   _Gestalt   =  $A1AD;
  20865. BEGIN
  20866.   GestaltAvailable := TrapAvailable(_Gestalt);
  20867. END;
  20868.  
  20869. If you need to know at several different places in your application whether
  20870. Gestalt is available, it may be more efficient to define a global Boolean
  20871. variable that you can test before calling Gestalt. Listing 3-4 illustrates how
  20872. to do this. Once again, this code uses the TrapAvailable function defined
  20873. earlier.
  20874.  
  20875. Listing 3-4.  Using Gestalt to determine the Time Manager version
  20876.  
  20877. VAR
  20878.   hasGestalt:  Boolean;  {true if Gestalt is implemented}
  20879.  
  20880. hasGestalt := TrapAvailable(_Gestalt);
  20881.   .
  20882.   .
  20883.   .
  20884.  
  20885. IF hasGestalt THEN BEGIN
  20886.   myErr := Gestalt(gestaltTimeMgrVersion, myFeature);
  20887.   IF myErr <> noErr THEN
  20888.     DoError(myErr);
  20889. END;
  20890.  
  20891. This sample code returns (in the myFeature variable) the version of the Time
  20892. Manager available on the current machine. Before using that information, 
  20893. however, you should test the result code to make sure that Gestalt was able to
  20894. determine the requested information.
  20895.  
  20896. _______________________________________________________________________________
  20897.  
  20898. æKY Interpreting…Gestalt…Responses
  20899. æC »Interpreting Gestalt Responses                                Compatibility Guidelines
  20900. _______________________________________________________________________________
  20901.  
  20902. When your application calls Gestalt to get information about the operating
  20903. environment, the meaning of the value that Gestalt returns in the response
  20904. parameter depends on the selector code with which it was called. For example, a
  20905. call to Gestalt using the gestaltTimeMgrVersion selector returns a version code
  20906. in the low-order byte of the response parameter. In this case, a returned value
  20907. of 3 indicates that the extended Time Manager is available.
  20908.  
  20909. In almost all cases, the last few characters in the selector’s symbolic name
  20910. form a suffix that indicates what type of value you can expect Gestalt to
  20911. return. For example, if the final characters in a Gestalt selector are Addr,
  20912. then Gestalt returns an address in the response parameter. The following list
  20913. shows the meaningful suffixes.
  20914.  
  20915. Suffix  Meaning
  20916.  
  20917. Addr    The returned value is an address.
  20918.  
  20919. Attr    The returned value is a range of bits, the meaning of which must be
  20920.         determined by comparison with a list of constants. Note that bit 0 is
  20921.         the least significant bit of the long word.
  20922.  
  20923. Count   The returned value is a number indicating how many of the indicated type
  20924.         of item exist.
  20925.  
  20926. Size    The returned value is a size. Sizes reported by Gestalt are usually in 
  20927.         bytes.
  20928.  
  20929. Type    The returned value is an index describing a particular type of feature.
  20930.  
  20931. Version The returned value is a version number. Implied decimal points may
  20932.         separate digits of the returned value. For example, a value of $0603
  20933.         returned in response to the gestaltSystemVersion selector indicates 
  20934.         that system software version 6.0.3 is present.
  20935.  
  20936. Selectors that have the suffix Attr deserve special attention; they cause
  20937. Gestalt to return a bit field that your application must interpret in order to
  20938. determine whether a desired feature is present. For example, the gestaltOSAttr
  20939. selector requests information about a number of Operating System features. To
  20940. determine whether a particular Operating System feature is available, you need
  20941. to read the appropriate bit in the response parameter, as Listing 3-5
  20942. illustrates.
  20943.  
  20944. Listing 3-5.  Interpreting a bit field response
  20945.  
  20946. VAR
  20947.   myBit:  Integer;
  20948.   myFeature:  LongInt;
  20949.   myErr:  Integer;
  20950.  
  20951. IF hasGestalt THEN BEGIN
  20952.   myErr := Gestalt(gestaltOSAttr, myFeature);
  20953.   IF myErr <> noErr THEN
  20954.     DoError(myErr)
  20955.   ELSE BEGIN
  20956.     myBit := gestaltTempMemSupport;
  20957.     IF BTst(myFeature, 31-myBit) = TRUE THEN
  20958.       WriteLn('temporary memory support available')
  20959.     ELSE
  20960.       WriteLn('temporary memory support not available');
  20961.   END;
  20962. END;
  20963.  
  20964. This code uses the MPW function BTst to determine if the appropriate bit in
  20965. Gestalt’s response is equal to 1. Your development system may have other ways of
  20966. testing the appropriate bit.
  20967.  
  20968. _______________________________________________________________________________
  20969.  
  20970. æKY Interpreting…Responses…to…Environmental…Selectors
  20971. æC »Interpreting Responses to Environmental Selectors             Compatibility Guidelines
  20972. _______________________________________________________________________________
  20973.  
  20974. Gestalt returns one of the following responses when passed a predefined
  20975. environmental selector.
  20976.  
  20977. gestaltVersion
  20978.  
  20979. Returns the version of Gestalt. The current version is 1, corresponding to a
  20980. returned value of $0001.
  20981.  
  20982. gestaltAddressingModeAttr
  20983.  
  20984. Returns information about the current addressing.
  20985.  
  20986. CONST
  20987. gestalt32BitAddressing  = 0;
  20988. gestalt32BitSysZone     = 1;
  20989. gestalt32BitCapable     = 2;
  20990.  
  20991. The gestalt32BitAddressing attribute indicates that the machine started up with
  20992. 32-bit addressing. The gestalt32BitSysZone attribute indicates that the system
  20993. heap has 32-bit clean block headers (regardless of the type of addressing the
  20994. machine started up in). See the Memory Management chapter for more information
  20995. about 32-bit addressing.
  20996.  
  20997. gestaltAliasMgrAttr
  20998.  
  20999. Returns information about the Alias Manager.
  21000.  
  21001. CONST
  21002. gestaltAliasMgrPresent  = 0;
  21003.  
  21004. gestaltAppleTalkVersion
  21005.  
  21006. Returns the version number of the AppleTalk driver currently installed. In
  21007. particular, it returns the version number of the MPP driver. The version number
  21008. is placed into the low-order byte of the result, so you should ignore the three
  21009. high-order bytes of the result. If an AppleTalk driver is not currently open,
  21010. the response parameter is 0. The driver will not be opened until the user
  21011. requests a network service (such as Chooser).
  21012.  
  21013. gestaltAUXVersion
  21014.  
  21015. Returns the version of A/UX if it is currently executing. The result is placed
  21016. into the lower word of the response parameter. If A/UX is not executing, Gestalt
  21017. returns gestaltUnknownErr.
  21018.  
  21019. gestaltCTBVersion
  21020.  
  21021. Returns the version number of the Communications Toolbox.
  21022.  
  21023. gestaltDBAccessMgrAttr
  21024.  
  21025. Returns information about the Database Access Manager.
  21026.  
  21027. CONST
  21028. gestaltDBAccessMgrPresent  = 0;
  21029.  
  21030. gestaltEditionMgrAttr
  21031.  
  21032. Returns information about the Edition Manager.
  21033.  
  21034. CONST
  21035. gestaltEditionMgrPresent  = 0;
  21036.  
  21037. gestaltAppleEventsAttr
  21038.  
  21039. Returns information about AppleEvents.
  21040.  
  21041. CONST
  21042. gestaltAppleEventsPresent  = 0;
  21043.  
  21044. gestaltFolderMgrAttr
  21045.  
  21046. Returns information about the Folder Manager.
  21047.  
  21048. CONST
  21049. gestaltFolderMgrPresent  = 0;
  21050.  
  21051. gestaltFontMgrAttr
  21052.  
  21053. Returns information about the Font Manager.
  21054.  
  21055. CONST
  21056. gestaltOutlineFonts  = 0;
  21057.  
  21058. gestaltFPUType
  21059.  
  21060. Returns a value that indicates the type of floating-point coprocessor currently
  21061. installed, if any.
  21062.  
  21063. CONST
  21064. gestaltNoFPU          = 0;
  21065. gestalt68881          = 1;
  21066. gestalt68882          = 2;
  21067.  
  21068. gestaltHardwareAttr
  21069.  
  21070. Returns information about the hardware configuration of the machine.
  21071.  
  21072. CONST
  21073. gestaltHasVIA1       = 0;
  21074. gestaltHasVIA2       = 1;
  21075. gestaltHasASC        = 3;
  21076. gestaltHasSCC        = 4;
  21077. gestaltHasSCSI       = 7;
  21078.  
  21079. gestaltHelpMgrAttr
  21080.  
  21081. Returns information about the Help Manager.
  21082.  
  21083. CONST
  21084. gestaltHelpMgrPresent  = 0;
  21085.  
  21086. gestaltKeyboardType
  21087.  
  21088. Returns a value that indicates the type of keyboard that is currently attached
  21089. to the system.
  21090.  
  21091. CONST
  21092. gestaltMacKbd          = 1;
  21093. gestaltMacAndPad       = 2;
  21094. gestaltMacPlusKbd      = 3;
  21095. gestaltExtADBKbd       = 4;
  21096. gestaltStdADBKbd       = 5;
  21097. gestaltPrtblADBKbd     = 6;
  21098. gestaltPrtblISOKbd     = 7;
  21099. gestaltStdISOADBKbd    = 8;
  21100. gestaltExtISOADBKbd    = 9;
  21101.  
  21102. If the Apple Desktop Bus™ is in use, there may be multiple keyboards or other
  21103. ADB devices attached to the machine. Gestalt returns the type of the keyboard on
  21104. which the last keystroke occurred.
  21105.  
  21106. gestaltLowMemorySize
  21107.  
  21108. Returns the size (in bytes) of the low-memory area. The low-memory area is used
  21109. for vectors, global variables, and dispatch tables.
  21110.  
  21111. gestaltLogicalRAMSize
  21112.  
  21113. Returns the amount of logical memory available. This value is the same as that
  21114. returned by gestaltPhysicalRAMSize when virtual memory is not installed. On some
  21115. machines, however, this value might be less than the value returned by
  21116. gestaltPhysicalRAMSize, because some RAM may be used by the video display and
  21117. the Operating System.
  21118.  
  21119. gestaltMiscAttr
  21120.  
  21121. Returns information about miscellaneous pieces of the Operating System or
  21122. hardware configuration. Currently only one value is returned.
  21123.  
  21124. CONST
  21125. gestaltScrollingThrottle  = 0;
  21126.  
  21127. gestaltMMUType
  21128.  
  21129. Returns a value that indicates the type of MMU currently installed, if any.
  21130.  
  21131. CONST
  21132.  
  21133. gestaltNoMMU      = 0;
  21134. gestaltAMU        = 1;
  21135. gestalt68851      = 2;
  21136. gestalt68030MMU   = 3;
  21137.  
  21138. gestaltNotificationMgrAttr
  21139.  
  21140. Returns information about the Notification Manager.
  21141.  
  21142. CONST
  21143. gestaltNotificationMgrPresent  = 0;
  21144.  
  21145. gestaltOSAttr
  21146.  
  21147. Returns general information about the Operating System, such as whether
  21148. temporary memory handles are real handles. The low-order bits of the response
  21149. parameter are interpreted as bit flags. A flag is set to 1 to indicate that the
  21150. corresponding feature is available. Currently the following bits are
  21151. significant:
  21152.  
  21153. CONST
  21154. gestaltSysZoneGrowable     = 0;
  21155. gestaltLaunchCanReturn     = 1;
  21156. gestaltLaunchFullFileSpec  = 2;
  21157. gestaltLaunchControl       = 3;
  21158. gestaltTempMemSupport      = 4;
  21159. gestaltRealTempMemory      = 5;
  21160. gestaltTempMemTracked      = 6;
  21161. gestaltIPCSupport          = 7;
  21162. gestaltSysDebuggerSupport  = 8;
  21163.  
  21164. See the Memory Management chapter in this volume for a full explanation of the
  21165. temporary memory features and the Process Management chapter for a full
  21166. explanation of the launch control features.
  21167.  
  21168. gestaltLogicalPageSize
  21169.  
  21170. Returns the logical page size. This value is an unknown on 68000-based machines,
  21171. since such machines do not have logical pages. On those machines, Gestalt
  21172. returns an error.
  21173.  
  21174. gestaltPowerMgrAttr
  21175.  
  21176. Returns information about the Power Manager, if present.
  21177.  
  21178. CONST
  21179. gestaltPMgrExists   = 0;
  21180. gestaltPMgrCPUIdle  = 1;
  21181. gestaltPMgrSCC      = 2;
  21182. gestaltPMgrSound    = 3;
  21183.  
  21184. gestaltPPCToolboxAttr
  21185.  
  21186. Returns information about the capabilities of the PPC Toolbox.
  21187.  
  21188. CONST
  21189. gestaltPPCToolboxPresent  = 0;
  21190. gestaltPPCRealTime        = 1;
  21191.  
  21192. gestaltProcessorType
  21193.  
  21194. Returns a value that indicates the type of processor that is currently running.
  21195.  
  21196. CONST
  21197. gestalt68000  = 1;
  21198. gestalt68010  = 2;
  21199. gestalt68020  = 3;
  21200. gestalt68030  = 4;
  21201.  
  21202. gestaltParityAttr
  21203.  
  21204. Returns information about the parity-checking abilities of the machine.
  21205.  
  21206. CONST
  21207. gestaltHasParityCapability  = 0;
  21208. gestaltParityEnabled        = 1;
  21209.  
  21210. Note that parity is not considered to be enabled unless all installed memory is
  21211. parity RAM.
  21212.  
  21213. gestaltQuickdrawVersion
  21214.  
  21215. Returns a 2-byte value indicating the version of QuickDraw currently present.
  21216. The high-order byte of that number represents the major revision number, and the
  21217. low-order byte represents the minor revision number. For example, the Macintosh
  21218. IIci contains QuickDraw version 2.01 in ROM; on that machine, Gestalt returns
  21219. the value $0201.
  21220.  
  21221. CONST
  21222. gestaltOriginalQD  = $000;
  21223. gestalt8BitQD      = $100;
  21224. gestalt32BitQD     = $200;
  21225.  
  21226. Values having a major revision number of 1 and 2 indicate that Color QuickDraw
  21227. is available, in either the 8-bit or 32-bit version. These results do not,
  21228. however, indicate whether a color monitor is attached to the system. You need to
  21229. use high-level QuickDraw routines to obtain that information.
  21230.  
  21231. gestaltPhysicalRAMSize
  21232.  
  21233. Returns the number of bytes of physical RAM currently installed.
  21234.  
  21235. gestaltResourceMgrAttr
  21236.  
  21237. Returns information about the capabilities of the Resource Manager.
  21238.  
  21239. CONST
  21240. gestaltPartialRsrcsExist  = 0;
  21241. gestaltDecompression      = 1;
  21242.  
  21243. gestaltScriptMgrVersion
  21244.  
  21245. Returns the version number of the Script Manager.
  21246.  
  21247. gestaltScriptCount
  21248.  
  21249. Returns the number of scripts currently active.
  21250.  
  21251. gestaltSoundAttr
  21252.  
  21253. Returns information about the sound capabilities of the machine.
  21254.  
  21255. CONST
  21256. gestaltStereoCapability  = 0;
  21257. gestaltStereoMixing      = 1;
  21258.  
  21259. The response gestaltStereoCapability indicates that the Sound Manager can play
  21260. stereo sounds. The response gestaltStereoMixing indicates that the sound
  21261. hardware of the machine mixes both left and right channels of stereo sound into
  21262. a single audio signal for the internal speaker.
  21263.  
  21264. gestaltTextEditVersion
  21265.  
  21266. Returns a value that indicates which version of TextEdit is present.
  21267.  
  21268. CONST
  21269. gestaltTE1  = 1;
  21270. gestaltTE2  = 2;
  21271. gestaltTE3  = 3;
  21272. gestaltTE4  = 4;
  21273.   
  21274. See the TextEdit chapter in this volume for further information on the
  21275. capabilities of these enhanced versions of TextEdit.
  21276.  
  21277. gestaltTimeMgrVersion
  21278.  
  21279. Returns a value that indicates the version of the Time Manager that is present.
  21280.  
  21281. CONST
  21282. gestaltStandardTimeMgr  = 1;
  21283. gestaltRevisedTimeMgr   = 2;
  21284. gestaltExtendedTimeMgr  = 3;
  21285.  
  21286. See the Time Manager chapter in this volume for a complete explanation of the
  21287. capabilities of each of these three versions.
  21288.  
  21289. gestaltVMAttr
  21290.  
  21291. Returns information about virtual memory.
  21292.  
  21293. CONST
  21294. gestaltVMPresent  = 1;
  21295. _______________________________________________________________________________
  21296.  
  21297. æKY Interpreting…Responses…to…Informational…Selectors
  21298. æC »Interpreting Responses to Informational Selectors             Compatibility Guidelines
  21299. _______________________________________________________________________________
  21300.  
  21301. Gestalt returns the following responses when passed a predefined informational
  21302. selector.
  21303.  
  21304. † Warning:  Never infer the existence of certain hardware or software features
  21305. from the responses that Gestalt returns to your application when you pass it
  21306. these selectors.Ê
  21307.  
  21308. gestaltMachineType
  21309.  
  21310. Returns one of the following values, indicating the type of machine on which the
  21311. application is currently running.
  21312.  
  21313. CONST
  21314. gestaltClassic   = 1;  {Macintosh 128K}
  21315. gestaltMacXL     = 2;  {Macintosh XL}
  21316. gestaltMac512KE  = 3;  {Macintosh 512KE }
  21317. gestaltMacPlus   = 4;  {Macintosh Plus}
  21318. gestaltMacSE     = 5;  {Macintosh SE}
  21319. gestaltMacII     = 6;  {Macintosh II}
  21320. gestaltMacIIx    = 7;  {Macintosh IIx}
  21321. gestaltMacIIcx   = 8;  {Macintosh IIcx}
  21322. gestaltMacSE030  = 9;  {Macintosh SE/30}
  21323. gestaltPortable  = 10; {Macintosh Portable}
  21324. gestaltMacIIci   = 11; {Macintosh IIci}
  21325.   
  21326. Note that the machine type does not indicate which version or size of ROM is
  21327. installed. To determine that information, you should use the two selectors
  21328. gestaltROMSize and gestaltROMVersion.
  21329.  
  21330. gestaltROMSize
  21331.  
  21332. Returns the size of the installed ROM. The value is returned in a word.
  21333.  
  21334. gestaltROMVersion
  21335.  
  21336. Returns the version number of the installed ROM.
  21337.  
  21338. gestaltSystemVersion
  21339.  
  21340. Returns the version number of the currently active System file. This number is
  21341. represented as two byte-long numbers. For example, if your application is
  21342. running in version 6.0.4, then Gestalt returns the value $0604. You should
  21343. ignore the high-order word of the returned value.
  21344.  
  21345. _______________________________________________________________________________
  21346.  
  21347. æKY Adding…Gestalt…Selectors
  21348. æC »Adding Gestalt Selectors                                      Compatibility Guidelines
  21349. _______________________________________________________________________________
  21350.  
  21351. You can add a new selector code to those already understood by Gestalt by
  21352. calling the NewGestalt function. The NewGestalt function requires two
  21353. parameters. The first parameter is the new selector to be registered. The second
  21354. parameter is the address of a selector function, a function that is to be
  21355. executed by Gestalt when it needs to determine what value to pass back when it
  21356. is called with the new selector code.
  21357.  
  21358. The selector code is a four-character sequence of type OSType. For example, 
  21359. Carl’s Object-Oriented Linker might register itself using the selector code 
  21360. 'COOL'. If you have registered a creator string with Apple, you are strongly
  21361. encouraged to use that sequence as your selector code.
  21362.  
  21363. Note:  Apple reserves for its own use all four-character sequences consisting
  21364. solely of lowercase letters and nonalphabetic ASCII characters.
  21365.  
  21366. The selector function whose address you specify when registering a new Gestalt
  21367. selector code can be any function that resides in the system heap and whose
  21368. calling syntax conforms to that defined in “Specifying Gestalt Selector
  21369. Functions” later in this chapter. Listing 3-6 illustrates how to install a
  21370. simple function into the system heap and pass its address to NewGestalt.
  21371.  
  21372. Listing 3-6.  Installing a selector function into the system heap
  21373.  
  21374. PROGRAM NewGestaltSample;
  21375. USES
  21376.   Memtypes, OSIntf, ToolIntf,   {standard includes}
  21377.   PasLibIntf,        {for standard I/O, etc.}
  21378.   GestaltEqu,       {for Gestalt}
  21379.   Traps;        {for trap numbers}
  21380. CONST
  21381.   mySelector    = 'COOL';  {Gestalt function selector}
  21382.   gstFuncRsrcType  = 'GDEF';  {Gestalt function resource type}
  21383.   gstFuncRsrcID  = 128;  {Gestalt function resource ID}
  21384. VAR
  21385.   gestaltErr:    OSErr;  {error returned by Gestalt}
  21386.   gstFuncHandle:  Handle;  {handle to Gestalt function}
  21387.   oldGestaltFunc:  ProcPtr;  {pointer to old function}
  21388. BEGIN
  21389.   {first make sure that Gestalt is available}
  21390.   IF NOT TrapAvailable(_Gestalt) THEN
  21391.     BEGIN
  21392.       WriteLn('Gestalt is not implemented.');
  21393.       IEexit(1)
  21394.     END;
  21395.   {load Gestalt function resource into system heap}
  21396.   gstFuncHandle := GetResource(gstFuncRsrcType, gstFuncRsrcID);
  21397.   IF gstFuncHandle = NIL THEN
  21398.     BEGIN
  21399.       WriteLn('Could not load Gestalt function resource.');
  21400.       IEexit(1)
  21401.     END;
  21402.   {detach it from the resource map so it stays around}
  21403.   DetachResource(gstFuncHandle);
  21404.   {add the new selector; first assume that it doesn't already exist}
  21405.   gestaltErr := NewGestalt(mySelector, ProcPtr(gstFuncHandle^));
  21406.   IF gestaltErr <> noErr THEN
  21407.     BEGIN
  21408.       WriteLn('Could not add as a new selector.');
  21409.       {try to replace existing selector}
  21410.       gestaltErr := ReplaceGestalt(mySelector,
  21411.         ProcPtr(gstFuncHandle^), oldGestaltFunc);
  21412.       IF gestaltErr <> noErr THEN
  21413.       BEGIN
  21414.         WriteLn('Could not replace selector either.');
  21415.         IEexit(1);
  21416.       END
  21417.     END;
  21418.   WriteLn('Selector installed.');
  21419. END.
  21420.  
  21421. You can ensure that the new Gestalt selector function is installed into the
  21422. system heap by defining it as a resource (in this case, of type 'GDEF') whose
  21423. resource attributes are resSysHeap and resLocked (in other words, lock the
  21424. resource into the system heap). Listing 3-7 shows the relevant lines from a
  21425. Makefile.
  21426.  
  21427. Listing 3-7.  Makefile directives to create a 'GDEF' resource
  21428.  
  21429. GestaltFunc.p.o      ƒ  GestaltFunc.p
  21430.   Pascal GestaltFunc.p
  21431.  
  21432. NewGestaltSample    ƒƒ  GestaltFunc.p.o
  21433.   Link GestaltFunc.p.o -rn ∂
  21434.            -ra =resSysHeap,resLocked ∂
  21435.            -rt GDEF=128
  21436.            -o NewGestaltSample
  21437.  
  21438. Listing 3-8 shows the actual function definition, contained in the file
  21439. GestaltFunc.p.
  21440.  
  21441. Listing 3-8.  Defining a new Gestalt function
  21442.  
  21443. UNIT GestaltFunc;
  21444. INTERFACE
  21445.   USES
  21446.     GestaltEqu;      {for Gestalt}
  21447.   CONST
  21448.     myResult  = $87654321;  {Gestalt function response}
  21449.   FUNCTION gestaltCool (gestaltSelector: OSType;
  21450.             VAR gestaltResponse: LongInt) : OSErr;
  21451.  
  21452. IMPLEMENTATION
  21453.   FUNCTION gestaltCool;
  21454.     BEGIN
  21455.       gestaltResponse := myResult;  {return our response}
  21456.       gestaltCool := noErr;    {return no error}
  21457.     END;
  21458. END.
  21459.  
  21460. Because the new selector function resides in the system heap, Gestalt recognizes
  21461. and responds to the new selector until the machines restarts, even if your
  21462. application terminates before that time. As a result, you might want your
  21463. selector function to determine whether your application is still running before
  21464. returning a value to Gestalt. If your application has terminated, the selector
  21465. function should return an error.
  21466.  
  21467. Note that if you try to register a selector that has already been registered
  21468. with Gestalt, an error results.
  21469.  
  21470. _______________________________________________________________________________
  21471.  
  21472. æKY Modifying…Gestalt…Selectors
  21473. æC »Modifying Gestalt Selectors                                   Compatibility Guidelines
  21474. _______________________________________________________________________________
  21475.  
  21476. You can use the ReplaceGestalt function to modify the function that Gestalt
  21477. executes when passed a particular selector code. As with the function whose
  21478. address is passed to NewGestalt, the new function must must reside in the system
  21479. heap and have a calling syntax that conforms to that defined in “Specifying
  21480. Gestalt Selector Functions” later in this chapter. Listing 3-6 illustrates how
  21481. to replace a Gestalt selector function.
  21482.  
  21483. To allow the new function to call the function previously associated with the
  21484. selector in question, the ReplaceGestalt function returns the address of the
  21485. previous function.
  21486.  
  21487. If you attempt to redefine a selector that is not yet defined, an error is
  21488. returned; in that case, the address of the previous function is undefined.
  21489. Accordingly, you should always test the result code of ReplaceGestalt before
  21490. calling Gestalt with the selector in question.
  21491.  
  21492. Note:  If you modify the function associated with a predefined Gestalt selector,
  21493. do not use any bits in the response parameter that are not documented in this
  21494. chapter. Apple reserves all undocumented bits in the response parameter returned
  21495. by predefined Gestalt selectors.  
  21496. _______________________________________________________________________________
  21497.  
  21498. æKY Specifying…Gestalt…Selector…Functions
  21499. æC »Specifying Gestalt Selector Functions                         Compatibility Guidelines
  21500. _______________________________________________________________________________
  21501.  
  21502. When you call the NewGestalt and ReplaceGestalt functions, you need to supply
  21503. the address of a selector function that is called when some application passes
  21504. the specified new or replacement selector to Gestalt. This selector function
  21505. should have the following syntax and must reside in the system heap.
  21506.  
  21507. FUNCTION selectorFunction (selector: OSType; VAR response: LongInt) : OSErr;
  21508.  
  21509. When you pass the new or replacement selector to Gestalt, Gestalt calls the
  21510. specified selector function to determine the information that Gestalt should
  21511. pass back to the calling software. Your function should place the result in the
  21512. long integer pointed to by the response parameter and should return the result
  21513. code that Gestalt will return. This function should be as simple as possible and
  21514. cannot use global variables in the A5 world unless A5 is set up explicitly and
  21515. then restored upon exit. (See the Memory Management chapter in this volume for
  21516. an explanation of setting up and restoring the A5 world.) Other Gestalt
  21517. functions may be called using Gestalt from within this function.
  21518.  
  21519. _______________________________________________________________________________
  21520.  
  21521. æKY Gestalt…Manager…Routines
  21522. æC »GESTALT MANAGER ROUTINES                                      Compatibility Guidelines
  21523. _______________________________________________________________________________
  21524.  
  21525. This section describes the three functions in the Gestalt Manager—Gestalt,
  21526. NewGestalt, and ReplaceGestalt. They allow you, respectively, to determine what
  21527. hardware and software features are present in the operating environment, to add
  21528. new selectors to those understood by the Gestalt function, and to replace the
  21529. functions associated with known selectors.
  21530.  
  21531. _______________________________________________________________________________
  21532.  
  21533. æKY Getting…Information…About…the…Operating…Environment
  21534. æC »Getting Information About the Operating Environment           Compatibility Guidelines
  21535. _______________________________________________________________________________
  21536.  
  21537. Use the Gestalt function to obtain information about the operating environment.
  21538. The information you need is indicated by the selector parameter, which Gestalt
  21539. must already recognize.
  21540.  
  21541. FUNCTION Gestalt (selector: OSType; VAR response: LongInt) : OSErr;
  21542.  
  21543. Trap macro  _Gestalt
  21544. On entry    D0: selector code
  21545. On exit     A0: response
  21546.             D0: result code
  21547.  
  21548. Upon successful completion of the function, the response parameter contains the
  21549. information requested. Note that Gestalt returns the results from all function
  21550. selectors in a long integer, occupying 4 bytes. In some cases, not all 4 bytes
  21551. are needed to hold the returned information, in which case Gestalt places the
  21552. information in the low-order bytes of the response parameter.
  21553.  
  21554. Result codes
  21555. noErr                        0  No error
  21556. gestaltUnknownErr        –5550  Could not obtain the response
  21557. gestaltUndefSelectorErr  –5551  Undefined selector
  21558. _______________________________________________________________________________
  21559.  
  21560. æKY Adding…Selector…Codes
  21561. æC »Adding Selector Codes                                         Compatibility Guidelines
  21562. _______________________________________________________________________________
  21563.  
  21564. Use the NewGestalt function to add selector codes to those already recognized by
  21565. Gestalt.
  21566.  
  21567. FUNCTION NewGestalt (selector: OSType; selectorFunction: ProcPtr) : OSErr;
  21568.  
  21569. Trap macro  _NewGestalt
  21570. On entry    A0: address of new selector function
  21571.             D0: selector code
  21572. On exit     D0: result code
  21573.  
  21574. NewGestalt takes as parameters the selector to be registered and the function
  21575. that Gestalt calls when it receives this selector. The interface for the
  21576. selectorFunction function is defined in “Specifying Gestalt Selector Functions”
  21577. earlier in this chapter.
  21578.  
  21579. Result codes
  21580. noErr                      0  No error
  21581. memFullErr              –108  Ran out of memory
  21582. gestaltDupSelectorErr  –5552  Selector already exists
  21583. gestaltLocationErr     –5553  Function not in system heap
  21584. _______________________________________________________________________________
  21585.  
  21586. æKY Modifying…Selector…Codes
  21587. æC »Modifying Selector Codes                                      Compatibility Guidelines
  21588. _______________________________________________________________________________
  21589.  
  21590. The ReplaceGestalt function allows an application to replace the function that
  21591. is currently associated with a selector.
  21592.  
  21593. FUNCTION ReplaceGestalt (selector: OSType; selectorFunction: ProcPtr;
  21594.             VA